Professional Documents
Culture Documents
A. HENRICHSEN
27/10/1998
This thesis is prepared in partial fulfillment of the requirements for the degree of BSc. in Electrical Engineering.
Acknowledgements
I would like to give my thanks to the following people for all their help and advice.
Mr G. Tattersfield, Department of Electrical Engineering, for his guidance as my thesis supervisor.
Mr J. Pinto, MSc. Student at the University of Cape Town, for his help with the Atmel Microcontroller.
Mr J. Salzwedel, Student at the University of Cape Town, for being a co-operative partner in sharing the GPS receiver, implementing the principles of the GPS and
the construction of the final GPS container.
And finally to the people at `Avnet Kopp', for lending us their copy of the Motorola GPS manual, and for donating the Motorola voltage regulator and Atmel
microcontroller free of charge.
Declaration
The work was my own, although this project could not have been accomplished without the help of the people mentioned in the Acknowledgements. The breakdown
Circuit Implementation
I received substantial help in the design of the external RAM for the microcontroller from Mr J. Pinto. I was responsible for the PCB layout using the program
Tango PCB and the testing of the circuit. The boards were produced by the `Electronics Supermarket' in Cape Town.
Software Implementation
The C++ and assembly programs are my own, except for the help I received from Mr J. Pinto with the setting up of the RAM and ROM areas of the microcontroller.
Voltage Regulator
The voltage regulator used in the circuit was suggested by Mr N. Ballard from `Avnet Kopp'. The incorporation of the regulator into the circuit is entirely my own.
System Analysis
The final analysis of the GPS system is my own, as are the conlusions drawn.
Terms Of Reference
This Thesis was proposed by Mr G. Tattersfield, Programme Co-ordinator of Electro-Mechanical Engineering at the University of Cape Town. The briefing was
given on the 25 June 1998 and work commenced on the 13 July 1998.
Mr Tattersfield's specific instructions were:
2. To investigate different microcontrollers and choose the most appropriate device to interface the GPS and LCD.
3. The system should be controlled by a small keyboard.
4. The GPS should be powered by a battery.
5. The hand-in date for the thesis is the 28 October 1998.
Synopsis
This thesis describes the investigation undertaken in implementing a hand-held Global Positioning System (GPS).
The objectives of this thesis were to use the Motorola Oncore GPS Receiver (Serial No. R3111G1111) in an embedded application and to build a user-friendly GPS
system, which would display all basic features of the GPS on a Liquid Crystal Display (LCD). A software based program would be controlled using a certain
number of keys, which would in turn operate and control the LCD and GPS.
The project was approached by first interfacing the GPS receiver to the PC via the serial port and the LCD to the PC via the parallel port. By studying the protocols
of the GPS and LCD, a program was implemented in C++. The next step in the design was to replace the PC using a suitable microcontroller. This microcontroller
was chosen to be the Atmel 89C55, as it had the necessary program memory and ports to substitute the PC. In order to program the Atmel chip, the already
implemented C++ code was converted into assembly language using a cross compiler. The final circuit was designed around the Atmel 89C55 chip.
In order to make the system more versatile, the user is able to switch between the microcontroller and the PC. This was achieved by providing an RS-232 connector,
which lets the GPS communicate with any computer. Power is provided by either a car battery or a `Gel' cell battery.
The major conclusions that could be drawn from the investigation are:
1. Most functions (position, status, data) could be implemented with the GPS and displayed on the LCD.
2. The use of the Atmel 89C55 microcontroller made the implementation of software and hardware easy as much help was available.
3. The system was succesfully tested and the layout of the keyboard and LCD made the system easy to use.
A GPS system was succesfully built and demonstrated. Since time was limited, some functions were not able to be implemented. Thus the following
recommendations can be made to improve the system:
1. Display the data obtained from the GPS graphically using the existing LCD, instead of using text as at present.
2. Implement the NMEA format for GPS data output using the RS-232 serial port.
3. Add non-volatile memory in order to store data from the GPS to be used later.
4. Display maps and plot the current position using a bigger colour screen/LCD.
5. Implement Differential GPS to get better position accuracies.
Glossary
BMP
- Bitmap Image
CG RAM
- Character Generator Random Access Memory
GPS
Contents
1 Introduction
2 The Motorola Oncore GPS
2.1 Brief Description of GPS
2.2 Antenna Information
2.3 GPS Oncore Information
2.3.1 Electrical Specifications
2.3.2 The Serial Interface
2.4 Interface Protocol
2.4.1 Motorola Binary Format
2.4.2 Details of some Commands
2.5 NMEA Interface Standard
2.5.1 Brief Description of NMEA
2.5.2 Outline of Command Structure
3 The Graphics Liquid Crystal Display
3.1 Module Pin-out
3.2 Status Check
3.3 Setting the Cursor and Address Pointer
3.4 Generating User Defined Characters
3.5 Displaying Graphics
4 The Atmel 89C55 Microcontroller
4.1 External RAM
4.2 The Serial Port
4.3 The Keypad
4.4 Other Microcontroller Connections
5 Software Development
5.1 PC application
5.2 Microcontroller application
6 Description of Power Supply
6.1 Switching between the Microcontroller and PC
7 System Analysis and Errors
7.1 Keypad Scanning Routine
7.2 Microcontroller serial port
7.3 GPS Differential Mode
7.4 External RAM
7.5 LCD Contrast Voltage
8 Conclusion
9 Recommendations
10 Bibliography
A GPS Oncore Commands
B Almanac Parameters
C LCD Controller Notes
D Circuit Diagrams
E C++ Code
F Assembly Code
G Included Disc
List of Figures
2.1 Oncore GPS Receiver (from the `GT PLUS ONCORE RECEIVER' pamphlet, available from Motorola).
3.1 User defined character of the degree sign
3.2 Bitmap Image displayed on LCD
3.3 Graphics Data Format
4.1 External RAM taken and modified from [Atmel,1997]
4.2 Keypad used in this thesis
5.1 Program Flow Diagram
B.1 Details of Subframe 5
C.1 Character Code Map from the T6963C
D.1 Circuit Diagram for External RAM
D.2 Interface Diagram for LCD
List of Tables
2.1 Oncore Power - Data Connector Pin Assignments [Motorola, 1996].
2.2 Oncore Interface Protocol [Motorola, 1996]
3.1 Relationship between CG RAM and Offset register
5.1 Virtual KeyBoard
A.1 Commands from GPS used for Thesis
A.2 NMEA Commands
A.3 Format Commands
B.1 Parameters of Subframe 4 and 5
Chapter 1
Introduction
This thesis sets out the results of the design and construction of a hand-held GPS receiver system.
The NAVigation Satellite and Ranging (NAVSTAR) GPS is an all weather, radio based, satellite navigation system that enables users to accurately determine 3-
dimensional position, velocity and time worldwide. The GPS system has been developed by the US Department of Defense and the service it provides is free to an
unlimited number of users [Motorola, 1996]. Receivers like the Motorola Oncore are inexpensive and easily obtainable and allow the inclusion of the receiver in
embedded applications. This gives the designer the freedom of designing a system suitable to a wide range of people [Motorola, 1996].
The Objectives of this thesis was to build a GPS system with the following aspects:
1. Must be hand-held.
2. Must be able to display all relevant information on a Graphics LCD.
3. The interfacing must be done using a microcontroller.
The thesis is restricted to the objectives outlined above due to the limited time that was available. It is up to the recommendations to provide details of other aspects
that could be included in a GPS system.
This thesis will first investigate the protocols associated with the Motorola Oncore GPS Receiver and the functions to be included in the project. Based on this
information and the visual requirements needed to display all necessary data, the graphics LCD screen is discussed. The method of displaying a bitmap image is
outlined here in detail. The choice of the Atmel 89C55 microcontroller will be discussed next, focusing on the suitability as an interface between the GPS and LCD.
Following this, there will be certain sections describing software development and the final circuit will be described with the chosen power supply. The whole
system will be analysed and discussed. Finally, conclusions are made about the design and effectiveness of the GPS system and recommendations are made about
further improvements that could be implemented.
Chapter 2
The Motorola Oncore GPS
As the GPS receiver forms the central part of this thesis, the first thing to do was to get a good understanding of the functions and requirements this particular GPS
receiver can provide. This was done using the Motorola GT/UT Oncore User's Guide [Motorola, 1996].
Space Segment:
This consists of the 24 satellites that make up the GPS. These satellites are found in 6 orbital planes and are equally spaced about the equator and inclined at
55 degrees. The satellites are found at an altitude of 20 183km.
Ground Control Segment:
This segment consist of a master control center and a number of monitoring stations. This network of stations tracks the satellites and precisely determines
their orbits. At certain intervals they will update the almanac ephemeris and other system data which the satellites transmit to the users.
User Segment:
The user segment consists of all the GPS receivers. The GPS receiver's position is determined by the geometric intersection of several simultaneously
observed ranges (satellite to receiver distance) from the satellites with known co-ordinates in space. The receiver measures the time required for a satellite
signal to reach the receiver. This transmission time is determined using code correlation techniques. This means that each satellite has a unique code
sequence that is identical to a code sequence generated by the receiver. The receiver code is shifted until maximum correlation between the 2 codes exist.
This time shift is multiplied by the speed of light and gives the distance to each satellite. Factors like satellite and receiver clock errors and propagation
delays are included in that signal. A minimum of 4 satellites need to be tracked in order to solve for 4 unknown parameters (i.e. latitude, longitude, altitude
and clock offset). If one of these parameters is known and fixed, one only needs to track 3 satellites.
The Oncore receiver is capable of detecting the presence of an antenna. An antenna sense circuit can detect under current (open circuit), over current (shorted or
exceeding maximum receiver limits), or a valid antenna connection [Motorola, 1996].
The above information is available through 2 I/O messages, namely the `Position/Status/Data' and `Self-Test' message.
Figure 2.1: Oncore GPS Receiver (from the `GT PLUS ONCORE RECEIVER' pamphlet, available from Motorola).
The Oncore receiver operates on a +5 Vdc regulated power source. The power source chosen for this thesis will be described in detail later. The data I/O serial port
interface is inverted TTL (5 V logic). The receiver has a 10-pin, power/data connector and a miniature RF connector for the antenna connection [Motorola, 1996].
The following table lists the assigned signal connections of the Oncore receiver:
Table 2.1: Oncore Power - Data Connector Pin Assignments [Motorola, 1996].
5V PWR:
4.75 Vdc to 5.25 Vdc
Battery or Backup PWR:
2.5 Vdc to 5.25 Vdc
To connect the GPS Oncore receiver to a PC, the TTL signal levels of the receiver have to be converted to RS-232 signal levels (i.e. TTL: 0V to be converted to +3
to +25Volts and TTL: 5V to -3V to -25Volts) To achieve this, the MAX232 driver ( or LT1032 ) is placed in the circuit which operates from a +5V power supply
and uses a charge pump to generate the negative supply needed.
Format: Motorola
Type: Binary
Baud Rate: 9600bps
Data Bits: 8 bits
Start/Stop: 1/1
Parity: none
The I/O port on the receiver operates under interrupt control. The incoming data is stored in a buffer that is serviced by the Oncore every 1.0 seconds.
The Oncore Receiver uses binary data messages consisting of a number of binary characters. A data message can be divided into the following sections [Motorola,
1996]:
Message Start:
@@ - (2 x 40hex) denotes the start of the binary message
Message ID:
(A..Z)(a..z, A..Z) - ASCII upper-case letter, followed by an ASCII lower-case or upper-case letter. These 2 characters together identify the message type and
imply the correct message length and format.
Binary Data Sequence:
This consists of a variable number of bytes of binary data dependent on the command type.
Checksum:
C - This is the exculsive-or of all bytes after the @@ and prior to the checksum.
Message Terminator:
<CR> <LF> - carriage return and line feed characters denoting the end of the binary message.
Every Oncore receiver input command has a corresponding response message to determine if the command has been accepted or rejected. If a correct command has
been received, the receiver will perform the requested function.
A binary message is considered received if the following checks out:
● the message started with @@ and is terminated with a carriage return and line feed character.
● the message is the correct length for its type
● the checksum validates.
[Motorola, 1996]
The data field contains binary data which can either be integer or floating point data. Negative numbers are stored as two's complement numbers.
The Oncore receiver will reject the entire command if one of its input parameters is out of range. For example, to change the GMT offset, the range of hours to be
changed is between -23 and +23. If a command is send requesting to change the GMT offset to 24 hours, the entire command is rejected and the original setting is
kept.
Response messages are identified in the same way as the Oncore receiver decodes the commands.
As describing each of the commands will take up many pages, only some commands will be descibed in more detail. These are taken from [Motorola, 1996].
1. The structure of the `Latitude'command is highlighted. All other commands follow the same structure but may be of different lengths. Input Command: ¯
Poll current Latitude:
@@AdxxxxC<CR><LF>
where xxxx = 4 out of range bytes (99hex99hex99hex99hex)
Message length is 11 bytes.
To convert milliarcseconds to degrees, the following relationship is used: 1o = 3 600 000 mas
2. The `Position/Status/Data' command combines nearly all other commands. The response message contains the date, time, position, velocity, geometry, the
satellite visibility and tracking status, and the status of each of the 8 channels. The message length is 76 bytes. It is possible to poll the receiver once or to
request a updated message at certain intervals.
3. The Almanac data output message contains satellite data. This almanac data is loaded into the onboard RAM of the Oncore receiver and takes about 15
minutes after power-up to be broadcast from the satellites. As there are 34 satellites, there are 34 response messages. Almanac data is transmitted in words 3-
10 of subframe 5 (pages 1-25), and words 3-10 of subframe 4 (pages 2-5, 7-10, and 25) of the satellite broadcast message.
Appendix B shows the format of the parameters that are situated in words 3-10 [GPS ICD-200].
As this message requires a big buffer (1122 bytes at least) to store the values in, this command has only been implemented on the PC and not on the
microcontroller.
Due to time limitations, this format was not implemented. It is, however, compared to the Motorola Binary Format.
The National Marine Electronics Association (NMEA) developed this standard to allow a satisfactory direct data interface between electronic marine instruments,
navigation equipment and communications equipment. This standard defines electrical signal requirements, data transmission protocol and timing for a 4800-baud
serial data bus. The intended application for this standard is between a single TALKER to one or many LISTENERS in one-way serial data transmission. The data
and commands are in the form of ASCII characters and as in the Motorola binary format, certain sequences of ASCII characters convey information about the
position, altitude etc. Each ASCII character has 8 data bits with the most significant bit always set to zero. Valid characters are the ASCII characters from 20h to
7Eh except some characters defined as reserved characters [NMEA,1997].
The following gives an outline of the reply message the Oncore receiver will send to an electronic navigation instrument [NMEA,1997]:
Start of sentence:
This is the ASCII character `$'= 24h
[Adress field:] This field consists of 5 characters. The first 2 characters identify the TALKER. In the case of the GPS, this code consists of the 2 ASCII
characters `GP'. The last 3 characters are the sentence formatter or message ID.
Field delimiter:
The character `,' = 2Ch starts each field except the address and checksum fiels. If it is followed by a null field, it indicates that no data is present.
Data Sentence block:
This consists of a series of data fields containing all the data that is transmitted. The sequence is identified by the sentence formatter.
Checksum Delimiter:
The character `*' = 2Ah follows the last data field and indicates that a 2 byte hex value follows from the checksum.
Checksum field:
This is the same as in the Motorola Binary format: all data between the `$' and the `*' are exclusive-or'ed together.
Terminates the sentence:
To request such a message from the Oncore, the following command needs to be sent [Motorola, 1996]:
Start of command:
$PMOTG, where the P identifies the message as Proprietary format; MOT stands for Motorola and G for GPS.
[Command field:] This field consists of 3 characters and corresponds to the sentence formatter of the address field above. The Oncore receiver has 7 NMEA
commands which are outlined in Appendix A.
Update Rate:
4 bytes instruct the receiver to output the message once or continuously.
The command also includes field delimiters, a checksum field and the 2 terminating characters.
As can be seen above, the NMEA format is similar to the Motorola Binary Format. The NMEA Format makes it easier for an electronic navigation instrument that
supports NMEA to communicate with the GPS.
As the information from NMEA commands can also be requested through the Motorola Binary Format, the NMEA Format was not implemented. The project could
have been expanded to include an electronic navigation instrument that communicates with the GPS.
Chapter 3
The Graphics Liquid Crystal Display
One of the requirements for this thesis was to display all information from the GPS on a LCD. A Graphics display was chosen as the biggest text display only had 40
characters by 4 lines. The display used is a 240 X 64 pixel graphics display from Varitronix (MGL(S)-24064-G-LED03). This was the biggest display the budget
could afford. With a 6 X 8 character font, text of 40 characters by 8 lines could be displayed which is sufficient for this thesis.
This chapter will describe the LCD controller from Toshiba (T6963C) and how to display a uncompressed black and white bitmap image on the screen.
1. The supply voltage is +5 Volts with a negative contrast voltage of about -10 Volts. This contrast voltage depends on the display type and temperature. In the
final circuit a charge pump (LT1054) is included to generate the required negative voltage. As its input +12 Volts is used (directly from Car battery or `Gel'
cell battery) which is inverted to -12 Volts. A potentiometer is included in the circuit to enable a variable negative contrast voltage.
2. There are 4 control pins: /WR (Write), /RD (Read), /CE (Chip enable) and C\/D (data/command register). These pins are used to write data or commands,
or to read the status byte [Toshiba,1997].
Write data:
The data to be written should be set on D0-7 and
C/\D taken low
/WR taken low (/RD should be high)
/CE must be pulsed low for greater than 80ns
Write command:
The command should be set on D0-7 and
C/\D taken high
/WR taken low (/RD should be high)
/CE must be pulsed low for greater than 80ns
Read Status:
To check the status of the controller:
C/\D taken high
/RD taken low (/WR should be high)
/CE must be pulsed
After approximately 150ns the data can be read from D0-7
/CE taken high
3. This LCD enables the user to choose the font size of the text characters. The fonts available are either 8x8 or 6x8 pixels. A 6x8 font was chosen in order to
increase the number of characters per row to 40. Only 30 characters are available per row with an 8x8 font.
It was only possible to interface to the parallel port of the PC if the port was bidirectional. As some PC's only have an output port, a delay of 1ms was inserted before
writing the data. As the Atmel microcontroller has bidirectional ports, this was not needed as the status byte can be read directly.
The user can choose between either graphics or text mode. In text mode there are certain cursor functions: a 1-8 line cursor, blinking or on/off. The cursor is moved
according to the following equation:
where y = [0,8], x = [0,63] and BYTES PER ROW = 40 with a 6X8 font
FromJohn P. Beale's program (May 3-4, 1997, beale@best.com)
The cursor pointer is not automatically moved with each write. Only the address pointer is incremented / decremented to the next position. The address pointer is
also set up according to the above equation.
1. The `Offset Register' command is used to determine the external character CG RAM area. As seen in Appendix C, characters are already defined from 00h
to 7Fh. User defined characters can be from 80h to FFh in CG RAM.
The following table will help chosing the nescessary Offset register data [Toshiba,1997]:
As this LCD only has 8k of RAM available, only the first 4 offset data numbers are usable. The CG RAM area used was from 1800 to 1FFFh, so that
character 80h will take up locations 1C00 to 1C07h (1800h + 80h*8 lines). This meant using an offset register number of 3h.
To store this character in RAM, the address pointer has to be set to 1C00h and the 8 bytes from Figure 3.1 written to it. Setting then the address pointer to
80h will display the degree sign on the LCD.
1. To create an image in black and white the Microsoft Paint Program was used. A canvas exactly the same size, in pixels, as the LCD was set up in the paint
program.
2. This image was saved in uncompressed `Tiff' format, now stored in negative mode. A black pixel is thus stored as a logical `0' and a white pixel as a logical
`1'. As the LCD is in positive mode, the image will be inverted. To remedy this, the bits were inverted when writing to the LCD.
3. To convert the image into hexadecimal form, a freeware program called bin2hex.exe was used. It is available from the following website:
http://www.hantronix.com. This program creates a text file which can be edited to the user's needs. The bytes of the image are listed in the following way:
00 15 12 32 ac ...
4. A `Hantronix' Application Note [Hantronix] says that one must delete the first 25 bytes from that text file, as these bytes are part of the `Tiff' header. This
was found not to be true. The text file in question consisted of 2260 bytes. To subtract 25 would give 2235 bytes. The LCD only needs 1920 bytes (30 bytes
in a row by 64 pixels (rows)). Thus the `Tiff' header which should be subtracted is 340 bytes long.
5. When reformatting the text file (using a simple text editor) to be included in an assembly program, the bytes will look like the following (see also page 122):
6. The data is formatted as shown below: This applies to the 240X64 Pixel Display.
7. The graphics area in RAM needs to be set up to how many bytes later one wants the next line to start at. This can be the same number of bytes to fill one
line of the screen for most efficient use of the RAM. If one would set the number of bytes in RAM less than the number of bytes per row the image gets
corrupted as certain bits / bytes get overwritten. With an 8X8 font there are 30 bytes in a row as in the `Tiff' file. But as a 6X8 font is used, the RAM had to
be set up to 40 bytes per row. The following equation which sets the address for each of the bytes in the text file on the LCD is taken from John P. Beale's
program (May 3-4, 1997, beale@best.com):
where row = [0,63], column = [0,239] and BYTES PER ROW = 40 with a 6X8 font
To set the bits on the LCD the `Set bit within byte' command is used.
8. As mentioned above, the image consists of 1920 bytes. Most of the pixels on the image were not set. To compress the same image the number of interstitial
`zero' bytes were counted and replaced with a number representing the number of `zero' bytes.
In this way the image was compressed to ±1000 bytes. The display routine simply jumps over the number and offsets the address by the required number of bytes.
(The code which displays the image on the LCD is found on page 89-90.)
Chapter 4
The Atmel 89C55 Microcontroller
After interfacing the GPS and the LCD to the PC and implemeting the code in C++, it became evident that the microcontroller to be used had to have at least 16
kbytes of Onboard ROM. This came from the fact that the image and the C-code would take up much memory. The microcontroller also needed approximately 512
bytes of RAM, half of it used for the buffer to store the GPS data in and the rest for program variables. A UART serial port was also needed.
Two microcontrollers were considered: the XC68HC705C9A from Motorola and the 89C55 from Atmel. As the Motorola microcontroller was not available, the
Atmel microcontroller was chosen as it has 20 kbytes of Flash, 256 bytes of RAM and a UART serial port. Another interesting fact was that the Flash Memory was
electronically and not UV erasable and made debugging and program development faster. The only drawback was that not enough Onboard RAM was available.
The following figure shows the hardware configuration for accessing up to 2 kbytes of external RAM (see also Figure D.1):
The 3 lines from Port 2 were strapped to +5V as they were not needed. Port 0 supplied the address and data and only 256 bytes could be accessed, which gave an
overall total of 512 bytes of RAM.
In order to access the external RAM, the `movx' instruction was used instead of the normal `mov' instruction. The address is placed on Port 0 and is latched with the
`ALE' pin after which the data is read or written from RAM.
The Atmel 89C55 makes use of 4 register banks. Only register bank `zero' was used during program execution which meant that the other 3 register banks were used
as additional 21 bytes of RAM.
[Atmel,1997]
The serial port was setup so that it could generate an interrupt whenever it received an character, in this case from the Oncore GPS receiver. The characters are read
from the microcontroller serial buffer (SBUF) and stored in a temporary circular buffer.
Each pushbutton has 2 terminals with one connected to a column rail and the other to a row rail. The row and column rails are then connected to the microcontroller
Port 1. The columns are then driven low by the port and the rows are read in. If no key has been pressed, the rows read `1'. When a row is detected to be `0', it
indicates that a key has been pressed. To detect which key has been pressed, the microcontroller loops through each column, driving 1 column at a time low and
inspects the row. The row will be grounded when the column in which the key resides is driven low. In this way the keys can be identified. Each key has a number
associated with it and this number is stored in the global variable `key'.
This particular keypad is implemented to invoke an interrupt. The 2 rows are combined into an AND gate. As the rows are normally at a logic level `1' , the output
of the AND gate is also a `1'. When a key is pressed, the `1' to `0' transition at the AND gate will trigger the interrupt.
A debouncing scheme has also been implemented. After the pressed key has been identified, the rows are checked until the key has been released. Only then does
the program continue.
(The code which implements the keypad scanning is found on page 78.)
Chapter 5
Software Development
Two types of programs were implemented. A program was written in C++ for the PC and another was written in assembly language for the microcontroller. Both
programs are identical: they implement the same routines in different languages.
5.1 PC application
In order to get a better understanding of both the GPS and LCD, the thesis was first implemented on the PC. The GPS Oncore was connected to the PC via the serial
port and the LCD was connected to the PC via the parallel port. The program was developed using Borland C++ for DOS, as the author has had previous experience
with it.
The following diagram shows the program flow of the main routines:
If a key has been pressed, the program will decide which Menu to display and which command to send to the GPS. The GPS will then send information back. As the
serial port was interrupt driven, every time the GPS Oncore send back data, an interrupt service routine would store the incomming characters in an ringbuffer (see
code on page 57).The main program would then check to see if the headpointer and tailpointer of the ringbuffer are equal or not. If not equal, then the ringbuffer
received new data and a routine had to decide which command had been send back. A command is identified by the 3rd and 4th character of each sequence (see
Appendix A). For each command from the GPS Oncore there is a display function which operates on the data in the ringbuffer and displays it in the best possible
way (see code in Appendix E).
0123
*456
789
The program flow is exactly the same as for the PC. A cross-compiler was used to change the C++ code to assembler. As the Engineering Departement did not have
a cross-compiler, a demo cross-compiler was used. This cross-compiler (HI-TECH C compiler for the 8051) only generated 500 lines of assembly code. Therefore it
was nescessary to break up the C++ code into smaller pieces and cross-compile these sections individually. It was then nescessary to edit the assembly code and
insert the names of the allocated variables in RAM, as the cross-compiler did not do so.
Assembly code was not generated for all functions. The cross-compiler left it to the user to generate code for 32-bit division and displaying strings. 32-bit division
was implemented by means of successive subtraction [Yeralan S and Ahluwalia A, 1995].
If a subroutine is called, the return address is pushed onto the stack. On entering this subroutine (lcdprint), the return address is popped again from the stack into the
data pointer. This data pointer will now point to the first character of the string, `T'. The data pointer is incremented after each character is displayed. If the data
pointer points to a `0', the routine returns to the calling program. As the return address was already popped from the stack, a `jump' is made to the address pointed to
by the data pointer, which points now to the instruction after the `0' (see code on page 86).
As the LCD character generator RAM only displays one character at a time, a number consisting of several characters had to be split up into its individual
characters. For example, the number `125' had to be split up into `1', `2', and `5'. This was achieved by dividing the number by `10', storing the remainder in an array
and later displaying the variables in the array. To show how this works the above number is used:
The remainder numbers are stored in an array and then displayed individually (see code on page 106).
Chapter 6
Description of Power Supply
A prerequisite for this thesis was to make the GPS portable. This meant running the GPS of batteries. It was decided to use a `Gel' cell battery and as another
alternative a car battery. The `Gel' cell battery was chosen as it was small enough and is rechargeable. It supplies 12 Volts with 2.2Ah.
As the GPS, LCD and microcontroller need a +5 Volt supply, a voltage regulator was needed. The voltage regulator chosen initially was the LM340. This regulator
is designed to change only 10 Volts to the required 5 Volts by dissipating the extra power. Using the `Gel' cell battery with the LM340 wasn't so desirable as the
power regulator had to dissipate an extra 2 Volts. As the car battery supplies 14 Volts when the car is running and the `Gel' cell battery supplies 12 Volts, the
regulator finally chosen was the MC34167 from Motorola. This is a fixed frequency power-switching regulator which changes any voltage ranging from 7-35 Volts
to 5 Volts (see figure D.5).
The box which houses the GPS circuitry has an extra compartment to hold the `Gel' cell battery. In order to prevent connecting the car battery to the circuit while the
`Gel' cell battery is still in the compartment, the connector can only be plugged in inside the compartment with the `Gel' cell battery removed.
Chapter 7
System Analysis and Errors
The following sections will describe some areas in the GPS system where errors occur or where the design is not very efficient. The errors are mostly timing related,
as in the keypad scanning routine. Another factor which will be discussed is the expanding of the external RAM from 256 bytes to 2 kbytes.
The key debouncing routine is very efficient, although sometimes the keys react to fast by `jumping' over certain functions in the program. This could be due to the
fact that the microcontroller is too fast and already `sees' the next key being pressed. This is minimal though and does not really affect the program.
satellite code to give them accuracies of centimetres or millimetres. A civilian user could get an accuracy of 1-5 meters by using the GPS Oncore receiver in
differential mode (DGPS). This means that a link between a base station, of which the exact position is known and fixed, and a GPS receiver exist so that the GPS
receiver can receive correction messages from the base station. A base station can be a GPS receiver being at a fixed location sending its correction messages to
another receiver. The GPS GT Oncore receiver, like the one used in this project, is capable of accepting these messages through one of its pins (Pin 5). But as only
one GPS receiver was available, the differential mode could not have been implemented. The GPS receiver also has to be capable of generating these correction
messages. The VP Oncore receiver from Motorola is capable of generating these correction messages.
In South Africa there are some base stations where these correction messages are available. The user has to buy `airtime' from them in order to receive these. A
possible way of using the Oncore receiver in differential mode would be to have a cell-phone link between the base staion and the GPS receiver in order to receive
these correction messages.
Chapter 8
Conclusion
The project undertaken to design and build a GPS system was succesfully completed. The final system is hand-held, user-friendly and reliable. From the
implementation process and work carried out on the GPS, the following conclusions can be drawn:
1. Microcontroller. The use of the Atmel 8051 microcontroller made the implementation of software and hardware very easy, as much help was available in
form of literature and cross-compilers.
2. Battery. The `Gel' cell battery is well suited for hand-held applications, and as it is rechargeable it can be used many times.
3. Method of Operation. The lay-out of the keyboard and LCD as well as the integration of the battery into a separate compartment made the system easy to
use. Making use of a virtual keyboard reduces the number of keys on the box but does not reduce the functionability.
4. Cost. The cost of this GPS system is ± R2000.00 which is initially more expensive than commercially available GPS systems that can be obtained
nowadays for less and are much smaller. But having a clear understanding of the Motorola Oncore GPS receiver means that more functions can be
implemented at a later stage to the user's preferences.
Chapter 9
Recommendations
As time was limited, many functions of the Oncore receiver could not be implemented. Therefore the following recommendations can be made:
1. Implement the NMEA protocol and use an electronic navigation system to communicate with the GPS.
2. Use the LCD more extensively by displaying the position of the GPS receiver or satellites graphically, instead of only using text.
3. Add non-volatile external memory to record data (i.e. position) in order to recall it later, or use it with the PC together to plot co-ordinates on a map.
4. Display a map and plot the current position on it, using a bigger colour screen.
5. Implement Differential GPS using the existing GPS receiver to get better position accuracies.
Bibliography
[Atmel,1997]
Atmel Corporation Microcontroller Data Book, San Jose California, 1997.
[GPS ICD-200]
GPS Interface Control Document: p86,p123-130
[Hantronix]
A simple way to create Bitmap Images for Graphics LCD's
[Motorola, 1996]
Motorola, GT/UT Oncore User's Guide, p2.1-2.3, 3.2-3.3, 3.7, 5.1-5.3, 6.1-6.45.
[NMEA,1997]
National Marine Electronics Association, NMEA 0183, Standard for Interfacing Marine Electronic Devices, Version 2.20, January1, 1997.
[Toshiba,1997]
Toshiba T6963C Data Sheet, Toshiba Corporation, 07/04/1997
[Yeralan S and Ahluwalia A, 1995]
Programming and Interfacing the 8051 Microcontroller, Addison-Wesley Publishing Comapany, Massachusetts: p75-111, p176-181, p185-195.
Appendix A
GPS Oncore Commands
Function Description Binary Command
Time Time of day @@Aa
Time GMT Offset @@Ab
Time Date @@Ac
Position Latitude @@Ad
Position Longitude @@Ae
Position Height @@Af
Position Satellite Mask Angle @@Ag
Receiver Atmosphere Correction Mode @@Aq
Time Time Mode @@Aw
Receiver Visible Satellite Status message @@Bb
Almanac Almanac Data Output @@Be
Time Leap Second Pending Status @@Bj
Receiver Set-to-Defaults @@Cf
Receiver Receiver ID @@Cj
Position Position/Status/Data @@Ea
Receiver Self-Test @@Fa
The following 2 commands are used with the NMEA data format:
Appendix B
Almanac Parameters
Parameters No. of Bits Scale Factor Units
e 16 2-21 dimensionless
toa 8 212 seconds
δi** 16* 2-19 semi-circles
Omegadot 16* 2-38 semi-circles/second
(A)1/2 24 2-11 meters1/2
(Omega)0 24* 2-23 semi-circles
ω 24* 2-23 semi-circles
* These parameters are represented in 2's Complement with the sign bit in the MSB.
** Relative to 0.3 semi-circles.
The following pages of subframe 4 have the same format as above: 2-5, 7-10.
Appendix C
LCD Controller Notes
Appendix D
Circuit Diagrams
Appendix E
C++ Code
The following files make up the 'GPS' program in C++ code:
[Writegps.cpp (p50):] Includes the main program from which commands are send to the GPS and messages from the GPS are decoded.
Gps.h (p54):
Contains the function which sends characters to the GPS and reads characters from the ringbuffer.
Lcd.h (p56):
Contains lcd routines to display characters on the LCD.
Disp.h (p60):
Contains routines which format the data received from the GPS and display it.
Pic.h (p72):
Contains the array holding the bytes for the picture displayed on the LCD.
FILE: WRITEGPS.CPP
#include <conio.h>
#include <dos.h>
#include <math.h>
#include <string.h>
#include <bios.h>
#include "pic.h"
#include "lcd.h"
#include "gps.h"
#include "disp.h"
void main(void)
{
int num1, num2, num3;
int hours, minutes, sign, time, atmos, sat, fix, angle;
char index1, index2;
char s;
int flag = 1, tag = 1, check = 1, count = 0;
do
{
while(bufferin != bufferout)
{
index1 = Buffer();
index2 = Buffer();
index1 = Buffer();
index2 = Buffer();
tag = 1;
switch(index1)
{
case 'A':
switch(index2)
{
case 'a':
Disp_Aa(0);
break;
case 'b':
Disp_Ab();
break;
case 'c':
Disp_Ac(0);
break;
case 'd':
Disp_Ad(0);
break;
case 'e':
Disp_Ae(0);
break;
case 'f':
Disp_Af(0);
break;
case 'g':
Disp_Ag();
break;
case 'q':
Disp_Aq();
break;
case 'w':
Disp_Aw();
break;
}
break;
case 'B':
switch(index2)
{
case 'b':
Disp_Bb();
break;
case 'j':
Disp_Bj();
break;
}
break;
case 'C':
switch(index2)
{
case 'b':
Disp_Cb();
break;
case 'f':
Disp_Same(0);
break;
case 'j':
Disp_Cj();
break;
}
break;
case 'E':
switch(index2)
{
case 'a':
flag = Disp_Ea(flag);
break;
}
break;
case 'F':
switch(index2)
{
case 'a':
Disp_Fa();
break;
}
break;
case 'S':
switch(index2)
{
case 'z':
Disp_Same(1);
break;
}
break;
}
}
if(kbhit())
{
if(tag == 1)
{
num1 = 0;
tag = 0;
}
////////////////UNDO INTERRUPTS AGAIN//////////////////
else
num1 = Key_Press_0();
switch(num1)
{
/////////////////////////////////////////////////////////
case MAIN_MENU:
Main_Menu();
break;
case POS_STA_DAT:
Sub_Menu1();
num2 = Key_Press_1();
switch(num2)
{
case POS_STATUS_DATA:
Pos_Menu(check);
num3 = Key_Press_3();
switch(num3)
{
case POS_1:
Data_To_Gps(pos_status_data, 4, 1, 0, 0, 0);
if(count == 1)
{
flag = 1;
count = 0;
}
if(flag == 0)
{
flag = 2;
count = 1;
}
check = 1;
break;
case POS_2:
Data_To_Gps(pos_status_data, 4, 1, 10, 0, 0);
if(count == 1)
count = 0;
flag = 0;
check = 0;
break;
case POS_3:
Data_To_Gps(pos_status_data, 4, 1, 20, 0, 0);
if(count == 1)
count = 0;
flag = 0;
check = 0;
break;
case POS_4:
Data_To_Gps(pos_status_data, 4, 1, 30, 0, 0);
if(count == 1)
count = 0;
flag = 0;
check = 0;
break;
}
break;
case LATTITUDE:
Data_To_Gps(lattitude, 8, 0, 0, 0, 0);
break;
case LONGITUDE:
Data_To_Gps(longitude, 8, 0, 0, 0, 0);
break;
case HEIGHT:
Data_To_Gps(height, 9, 0, 0, 0, 0);
break;
case DATE:
Data_To_Gps(date, 8, 0, 0, 0, 0);
break;
case TIME_OF_DAY:
Data_To_Gps(time_of_day, 7, 0, 0, 0, 0);
break;
case SATELLITES:
Data_To_Gps(satellites, 5, 0, 0, 0, 0);
break;
case ALMANAC:
Data_To_Gps(almanac, 5, 0, 0, 0, 0);
break;
}
break;
////////////////////////////////////////////////
case GPS_MODES:
Sub_Menu2();
num2 = Key_Press_2();
if(check == 0)
{
lcd_clear_text(); //write spaces
cput(0x94);//Graphics OFF & Text ON, cursor blinking
switch(num2)
{
case GMT:
Gmt_Menu();
num3 = Key_Press_4();
switch(num3)
{
case GMT_POLL:
Data_To_Gps(gmt_poll, 7, 0, 0, 0, 0);
break;
case GMT_CHANGE:
lcd_clear_text(); //write spaces
cput(0x97);//Graphics OFF & Text ON, cursor blinking
if(s == '-')
sign = 0xFF;
else if(s == '+')
sign = 0;
case TIME_MODE:
Time_Menu();
num3 = Key_Press_4();
switch(num3)
{
case TIME_MODE_POLL:
Data_To_Gps(time_mode_poll, 5, 0, 0, 0, 0);
break;
case TIME_MODE_CHANGE:
Time_Change();
time = Key_Press_4() - 1;
Data_To_Gps(time_mode_change, 4, 1, time, 0, 0);
break;
}
break;
case LEAP_SECOND:
Data_To_Gps(leap_second, 5, 0, 0, 0, 0);
break;
case ATMOSPHERE:
Atmos_Menu();
num3 = Key_Press_4();
switch(num3)
{
case ATMOSPHERE_POLL:
Data_To_Gps(atmosphere_poll, 5, 0, 0, 0, 0);
break;
case ATMOSPHERE_CHANGE:
Atmos_Sub_Menu();
atmos = Key_Press_3() - 1;
Data_To_Gps(atmosphere_change, 4, 1, atmos, 0, 0);
break;
}
break;
case SATELLITE_MASK:
Mask_Menu();
num3 = Key_Press_4();
switch(num3)
{
case MASK_POLL:
Data_To_Gps(mask_poll, 5, 0, 0, 0, 0);
break;
case MASK_CHANGE:
Mask_Sub_Menu();
Numbers( 1 );
angle = Key_Press_6();
Data_To_Gps(mask_change, 4, 1, angle, 0, 0);
break;
}
break;
}
break;
///////////////////////////////////////////////////////////
case RECEIVER_FUNC:
Sub_Menu3();
num2 = Key_Press_0();
if(check == 0)
{
lcd_clear_text(); //write spaces
cput(0x94); //Graphics OFF & Text ON, cursor blinking
switch(num2)
{
case GPS_ID:
Data_To_Gps(gps_id, 4, 0, 0, 0, 0);
break;
case GPS_SELFTEST:
Data_To_Gps(gps_selftest, 4, 0, 0, 0, 0);
break;
case GPS_SET_DEFAULTS:
Data_To_Gps(gps_set_defaults, 4, 0, 0, 0, 0);
break;
}
break;
}
}
} while(num1 != 4);
FILE: GPS.H
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
int bufferin = 0;
int bufferout = 0;
int buffer[2049];
char gmt_poll[7]
= { '@', '@', 'A', 'b', 0xFF, 0xFF, 0xFF };
char gmt_change[4] = { '@', '@', 'A', 'b' };
char time_mode_poll[5]= { '@', '@', 'A', 'w', 0xFF };
char time_mode_change[4] = { '@', '@', 'A', 'w' };
char leap_second[5] = { '@', '@', 'B', 'j', 0 };
char atmosphere_poll[5] = { '@', '@', 'A', 'q', 0xFF };
char atmosphere_change[4] = { '@', '@', 'A', 'q' };
char mask_poll[5] = { '@', '@', 'A', 'g', 0xFF };
char mask_change[4] = { '@', '@', 'A', 'g' };
outp(0x20,0x20);
}
if(i > 2)
checksum ^= data[i];
}
checksum ^= var1 ^ var2 ^ var3;
if(flag == 1)
{
outp(PORT, var1); //send char to serial port
delay(1);
}
else if(flag == 2)
{
outp(PORT, var1); //send char to serial port
delay(1);
outp(PORT, var2); //send char to serial port
delay(1);
}
else if(flag == 3)
{
outp(PORT, var1); //send char to serial port
delay(1);
outp(PORT, var2); //send char to serial port
delay(1);
outp(PORT, var3); //send char to serial port
delay(1);
}
outp(PORT, checksum); //send char to serial port
delay(1);
outp(PORT, 0x0D); //send <CR> to serial port
delay(1);
outp(PORT, 0x0A); //send <LF> to serial port
delay(1);
}
int Buffer()
{
int ch;
ch = buffer[bufferout];
delay(2);
bufferout++;
if(bufferout == 2048)
bufferout = 0;
return ch;
}
b = b | Buffer();
}
return b;
}
void End()
{
int byte;
byte = Buffer();
byte = Buffer();
byte = Buffer();
}
FILE: LCD.H
//////////////////////////////////////////////////////
//Program to control a T6963C-based 240x64 pixel LCD display
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
void lcd_clear_graph() //clear graphics memory of LCD
{
int i;
dput(G_BASE%256);
dput(G_BASE>>8);
cput(0x24); //addrptr at address G_BASE
void lcd_clear_text()
{
int i;
temp = num;
while(1)
{
c = num % 10;
if(num == 0)
break;
}
if((f == 1) && (temp > 0) && (temp < 10))
{
array[count] = char(0);
count++;
}
for(i = count - 1; i >= 0 ; i--)
{
c = array[i] | 0x10;
if (c<0)
c=0;
dput(c); //write character
cput(0xc0); //increment memory ptr.
}
} //end lcd_print_num
}
temp = count1;
while(1)
{
n = num;
if((n < num) || (n > num))
{
num = num * 10;
count1++;
}
else if(n == num)
break;
}
n = num;
while(1)
{
c = n % 10;
if(n == 0)
break;
}
c = array[i] | 0x10;
count3++;
if (c<0)
c=0;
dput(c); //write character
cput(0xc0); //increment memory ptr.
}
}
else if(count2 <= count1)
{
c = 0x10;
dput(c); //write character
cput(0xc0); //increment memory ptr.
lcd_print(".");
count1--;
for(i = (count2 - 1); i >= 0 ; i--)
{
while((temp - 1) > count3)
{
c = 0x10;
} //end lcd_setpixel()
} //lcd_xy()
/* ===================================================
* Low-level I/O routines to interface to LCD display
* based on four routines:
*
* dput(): write data byte
* cput(): write control byte
* sget(): read status
* ===================================================
*/
//make sure control lines are at correct levels
void lcd_setup()
{
CEHI; //disable chip
RDHI; //disable reading from LCD
WRHI; //disable writing to LCD
CDHI; //command/status mode
} //end lcd_setup()
dput(BYTES_PER_ROW%256);
dput(BYTES_PER_ROW>>8);
cput(0x43); //n bytes per graphics line
dput(T_BASE%256);
dput(T_BASE>>8);
cput(0x40); //text memory at address T_BASE
dput(BYTES_PER_ROW%256);
dput(BYTES_PER_ROW>>8);
cput(0x41); //n bytes per text line
dput(0x00);
dput(0x00);
cput(0x21); //put cursor at (x,y) location
dput(0x1C);
cput(0xC0);
dput(0x14);
cput(0xC0);
dput(0x1C);
cput(0xC0);
dput(0x00);
cput(0xC0);
dput(0x00);
cput(0xC0);
dput(0x00);
cput(0xC0);
dput(0x00);
cput(0xC0);
dput(0x00);
cput(0xC0);
} //end lcd_init()
return(lcd_status);
} //sget()
void Disp_Pic()
{
int i = 0, j = 0, k; //generic counter
int num, no;
int counter = 0;
while(1)
{
num = Gps_pic_less[counter];
if(num > 1000)
{
for(k = 1000; k < num ; k++)
{
j += 8;
if(j == 240)
{
j = 0;
i++;
if(i == 64)
break;
}
}
}
else
{
for(k = 0; k < 8; k++)
{
no = num & 0x80;
num <<= 1;
if(no == 0x80)
lcd_setpixel(j + k, i); // draw pixel on LCD screen
}
j += 8;
if(j == 240)
{
j = 0;
i++;
if(i == 64)
break;
}
}
counter++;
}
}
FILE: DISP.H
#define MAIN_MENU 0
#define POS_STA_DAT 1
#define GPS_MODES 2
#define RECEIVER_FUNC 3
#define POS_STATUS_DATA 1
#define LATTITUDE 2
#define LONGITUDE 3
#define HEIGHT 4
#define DATE 5
#define TIME_OF_DAY 6
#define SATELLITES 7
#define ALMANAC 8
#define GMT 1
#define TIME_MODE 2
#define LEAP_SECOND 3
#define ATMOSPHERE 4
#define SATELLITE_MASK 5
#define GPS_ID 1
#define GPS_SELFTEST 2
#define GPS_SET_DEFAULTS 3
#define POS_1 1
#define POS_2 2
#define POS_3 3
#define POS_4 4
#define GMT_POLL 1
#define GMT_CHANGE 2
#define TIME_MODE_POLL 1
#define TIME_MODE_CHANGE 2
#define ATMOSPHERE_POLL 1
#define ATMOSPHERE_CHANGE 2
#define MASK_POLL 1
#define MASK_CHANGE 2
int lines;
int chars;
int key;
long byte;
char pole[2];
else
lines = l;
chars = c;
dput(chars);
dput(lines);
cput(0x21); //put cursor at (x,y) location
}
int Key_Press_0()
{
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x11B)
{
lines = 6;
break;
}
else if(key == 0x1C0D)
break;
else if(key == 0x4800)
{
if(lines > 3)
Cursor_Pos(-1, chars);
else if(lines == 3)
Cursor_Pos(5, chars);
}
else if(key == 0x5000)
{
if(lines < 5)
Cursor_Pos(10, chars);
else if(lines == 5)
Cursor_Pos(3, chars);
}
}
return (lines - 2);
}
int Key_Press_1()
{
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x11B)
{
lines = 9;
break;
}
else if(key == 0x1C0D)
break;
else if(key == 0x4800)
{
if(lines > 0)
Cursor_Pos(-1, chars);
else if(lines == 0)
Cursor_Pos(7, chars);
}
else if(key == 0x5000)
{
if(lines < 7)
Cursor_Pos(10, chars);
else if(lines == 7)
Cursor_Pos(0, chars);
}
}
return (lines + 1);
}
int Key_Press_2()
{
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x11B)
{
lines = 6;
break;
}
else if(key == 0x1C0D)
break;
else if(key == 0x4800)
{
if(lines > 1)
Cursor_Pos(-1, chars);
else if(lines == 1)
Cursor_Pos(5, chars);
}
else if(key == 0x5000)
{
if(lines < 5)
Cursor_Pos(10, chars);
else if(lines == 5)
Cursor_Pos(1, chars);
}
}
return lines;
}
int Key_Press_3()
{
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x11B)
{
lines = 6;
break;
}
else if(key == 0x1C0D)
break;
else if(key == 0x4800)
{
if(lines > 1)
Cursor_Pos(-1, chars);
else if(lines == 1)
Cursor_Pos(4, chars);
}
else if(key == 0x5000)
{
if(lines < 4)
Cursor_Pos(10, chars);
else if(lines == 4)
Cursor_Pos(1, chars);
}
}
return lines;
}
int Key_Press_4()
{
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x11B)
{
lines = 6;
break;
}
else if(key == 0x1C0D)
break;
else if(key == 0x4800)
{
if(lines > 3)
Cursor_Pos(-1, chars);
else if(lines == 3)
Cursor_Pos(4, chars);
}
else if(key == 0x5000)
{
if(lines < 4)
Cursor_Pos(10, chars);
else if(lines == 4)
Cursor_Pos(3, chars);
}
}
return (lines - 2);
}
char Key_Press_5()
{
char sign;
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x11B)
{
sign = '+';
break;
}
else if(key == 0x1C0D)
break;
else if((key == 0x4800) && (chars == 13))
{
if(lines > 5)
Cursor_Pos(-1, chars);
else if(lines == 5)
Cursor_Pos(6, chars);
}
else if((key == 0x5000) && (chars == 13))
{
if(lines < 6)
Cursor_Pos(10, chars);
else if(lines == 6)
Cursor_Pos(5, chars);
}
}
if(lines == 5)
sign = '-';
else if(lines == 6)
sign = '+';
return sign;
}
int Key_Press_6()
{
int num = 0, i, count = 0;
int yebo[5];
while(1)
{
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x11B)
{
num = 0;
break;
}
else if(key == 0x1C0D)
break;
else if((key == 0x4800) && (chars != 13))
{
if(lines > 4)
Cursor_Pos(-1, chars);
else if(lines == 4)
Cursor_Pos(6, chars);
}
else if((key == 0x5000) && (chars != 13))
{
if(lines < 6)
Cursor_Pos(10, chars);
else if(lines == 6)
Cursor_Pos(4, chars);
}
else if((key == 0x4800) && (chars == 13))
{
if(lines > 4)
Cursor_Pos(-1, chars);
else if(lines == 4)
Cursor_Pos(5, chars);
}
else if((key == 0x5000) && (chars == 13))
{
if(lines < 5)
Cursor_Pos(10, chars);
else if(lines == 5)
Cursor_Pos(4, chars);
}
else if((key == 0x4B00) && ((lines == 4) || (lines == 5)))
{
if(chars > 13)
Cursor_Pos(lines, chars - 3);
void Main_Menu()
{
Init_Text(0);
Cursor_Pos(3, 7);
void Sub_Menu1()
{
Init_Text(0);
Cursor_Pos(0, 7);
void Sub_Menu2()
{
Init_Text(0);
Cursor_Pos(1, 7);
void Sub_Menu3()
{
Init_Text(0);
Cursor_Pos(3, 11);
void Gmt_Menu()
{
Init_Text(0);
Cursor_Pos(3, 1);
void Time_Menu()
{
Init_Text(0);
Cursor_Pos(3, 1);
void Time_Change()
{
Init_Text(0);
Cursor_Pos(3, 1);
void Atmos_Menu()
{
Init_Text(0);
Cursor_Pos(3, 1);
void Atmos_Sub_Menu()
{
Init_Text(0);
Cursor_Pos(1, 1);
void Mask_Menu()
{
Init_Text(0);
Cursor_Pos(3, 1);
void Mask_Sub_Menu()
{
Init_Text(0);
if(flag == 0)
{
Init_Text(1);
lcd_xy(0,3); //first character, 3 line
lcd_print("Current Time: ");
}
if(flag == 1)
{
lcd_xy(17,0);
lcd_print("/ Time: ");
}
lcd_print_num(Buffer(),1);
lcd_print(":");
lcd_print_num(Buffer(),1);
lcd_print(":");
lcd_print_num(Buffer(),1);
lcd_print(" hours");
if(flag == 0)
End();
}
void Disp_Ab()
{
Init_Text(1);
byte = Buffer();
if(byte == 0)
lcd_print("+");
else
lcd_print("-");
lcd_print_num(Buffer(),0);
lcd_print(":");
lcd_print_num(Buffer(),0);
lcd_print(" hours");
End();
}
byte = Buffer();
lcd_print_num(Buffer(),1);
lcd_print("/");
lcd_print_num(byte,1);
lcd_print("/");
lcd_print_num(Bytes(1),0);
if(flag == 0)
End();
}
if(flag == 0)
{
Init_Text(1);
lcd_xy(0,1); //first character, 1 line
lcd_print("Lattitude(milliarcseconds or mas): ");
}
byte = Bytes(3);
if(flag == 0)
{
lcd_xy(5,2);
if(byte > 0)
{
lcd_print("+");
temp = byte;
}
else
{
lcd_print("-");
temp = -byte;
}
lcd_print_num(temp,0);
lcd_print("mas");
minutes = -minutes;
if(flag == 0)
End();
}
if(flag == 0)
{
Init_Text(1);
lcd_xy(0,1); //first character, 1 line
lcd_print("Longitude(milliarcseconds or mas): ");
}
byte = Bytes(3);
if(flag == 0)
{
lcd_xy(5,2);
if(byte > 0)
{
lcd_print("+");
temp = byte;
}
else
{
lcd_print("-");
temp = -byte;
}
lcd_print_num(temp,0);
lcd_print("mas");
}
else if(flag == 1)
{
lcd_xy(23,1); //first character, 3 line
lcd_print("/ ");
}
minutes = byte;
if(minutes < 0)
minutes = -minutes;
if(flag == 0)
End();
}
if(flag == 0)
{
Init_Text(1);
byte = Bytes(3);
height = byte;
lcd_print_float(height/100);
lcd_print("m");
if(flag == 0)
End();
void Disp_Ag()
{
Init_Text(1);
End();
}
void Disp_Aq()
{
Init_Text(1);
lcd_xy(0,3);
lcd_print("Atmospheric Correction Mode: ");
byte = Buffer();
lcd_xy(2,4);
if(byte == 0)
lcd_print("'0' = Ionosphere model disabled.");
else if(byte == 1)
lcd_print("'1' = Ionosphere model only enabled.");
else if(byte == 2)
lcd_print("'2' = Troposphreric model only enabled.");
else if(byte == 3)
lcd_print("'3' = Both models enabled.");
End();
}
void Disp_Aw()
{
Init_Text(1);
lcd_xy(0,3);
lcd_print("Current Time Mode: ");
byte = Buffer();
lcd_xy(2,4);
if(byte == 0)
lcd_print("'0' = GPS Time.");
else if(byte == 1)
lcd_print("'1' = UTC Time.");
End();
}
void Disp_Bb()
{
int num, i, key;
Init_Text(1);
lcd_xy(3,3);
lcd_print("Current Visible Satellites: ");
num = Buffer();
lcd_print_num(num,0);
lcd_xy(10,7);
lcd_print("...press enter for next page.");
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x1C0D)
break;
}
lcd_xy(0,1);
lcd_print("Satellite ");
lcd_print_num(i + 1,0);
lcd_print(": PN code ID: ");
lcd_print_num(Buffer(),0);
lcd_xy(0,2);
lcd_print("Doppler freq: ");
lcd_print_num(Bytes(1),0);
lcd_print("Hz");
lcd_xy(0,3);
lcd_print("Elevation: ");
lcd_print_num(Buffer(),0);
dput(0x80); //write character(degree sign)
cput(0xc0); //increment memory ptr.
lcd_xy(0,4);
lcd_print("Azimuth: ");
lcd_print_num(Bytes(1),0);
dput(0x80); //write character(degree sign)
cput(0xc0); //increment memory ptr.
byte = Buffer();
lcd_xy(0,5);
lcd_print("Satellite is ");
if(byte == 0)
lcd_print("healthy & not removed.");
else if(byte == 1)
lcd_print("healthy & removed.");
else if(byte == 2)
lcd_print("unhealthy & not removed.");
else if(byte == 3)
lcd_print("unhealthy & removed.");
lcd_xy(35,7);
lcd_print(".....");
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x1C0D)
break;
}
}
num = (12 - num) * 7;
for(i = 0; i < num; i++)
byte = Buffer();
End();
}
void Disp_Bj()
{
Init_Text(1);
lcd_xy(0,3);
lcd_print("Leap Second Pending Status: ");
byte = Buffer();
lcd_xy(2,4);
if(byte == 0)
lcd_print("'0' = No leap second pending.");
else if(byte == 1)
lcd_print("'1' = Addition of one second pending.");
else if(byte == 2)
lcd_print("'2' = Subtraction of one second pending.");
End();
}
void Disp_Cb()
{
int data_id, sv_id, frame, page;
int af0, af1;
int i;
float number;
char pm[2];
strcpy(pm, " ");
Init_Text(1);
frame = Buffer();
page = Buffer();
byte = Buffer();
data_id = ((byte & 0xC0) >> 6);
sv_id = (byte & 0x3F);
// cout << "\n\tData ID: " << data_id;
if( (page == 25) || (data_id == 2) || (sv_id > 32) )
{
for(i = 0; i < 23; i++)
byte = Buffer();
End();
}
else
{
lcd_xy(0,0);
lcd_print("SUBFRAME: ");
lcd_print_num(frame,0);
lcd_print(" / PAGE: ");
lcd_print_num(page,0);
lcd_xy(0,1);
lcd_print("SV ID: ");
lcd_print_num(sv_id,0);
byte = Bytes(1);
if((byte >> 15) & 1 == 1)
{
number = ((~byte + 1) * pow(2, -19) * M_PI) + (0.3 * M_PI);
number = -number;
strcpy(pm, "-");
}
else
number = (byte * pow(2, -19) * M_PI) + (0.3 * M_PI);
lcd_xy(0,4);
lcd_print("Orbital Inclination(rad): ");
lcd_print(pm);
lcd_print_float(number);
strcpy(pm, " ");
byte = Bytes(1);
if((byte >> 15) & 1 == 1)
{
number = (~byte + 1) * pow(2, -38)* M_PI;
number = -number;
strcpy(pm, "-");
}
else
number = byte * pow(2, -38)* M_PI;
lcd_xy(0,5);
lcd_print("Rate of Right Ascen(r/s): ");
lcd_print(pm);
lcd_print_float(number);
strcpy(pm, " ");
lcd_xy(11,1);
lcd_print("/ Health: ");
lcd_print_num(Buffer(),0);
lcd_xy(35,7);
lcd_print(".....");
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x1C0D)
break;
}
Init_Text(1);
byte = Bytes(2);
if((byte >> 23) & 1 == 1)
{
number = (~byte + 1) * pow(2, -23)* M_PI;
number = -number;
strcpy(pm, "-");
}
else
number = byte * pow(2, -23)* M_PI;
lcd_xy(0,1);
lcd_print("Right Ascen at TOA(rad): ");
lcd_print(pm);
lcd_print_float(number);
strcpy(pm, " ");
byte = Bytes(2);
if((byte >> 23) & 1 == 1)
{
number = (~byte + 1) * pow(2, -23)* M_PI;
number = -number;
strcpy(pm, "-");
}
else
number = byte * pow(2, -23)* M_PI;
lcd_xy(0,2);
lcd_print("Argument of Perigee(rad): ");
lcd_print(pm);
lcd_print_float(number);
strcpy(pm, " ");
byte = Bytes(2);
if((byte >> 23) & 1 == 1)
{
lcd_xy(0,4);
lcd_print("Af0 (s): ");
lcd_print(pm);
lcd_print_float(number);
strcpy(pm, " ");
af1 >>= 5;
if((af1 >> 10) & 0x01 == 1)
{
number = (~af0 + 1) * pow(2, -20);
number = -number;
strcpy(pm, "-");
}
else
number = af1 * pow(2, -38);
lcd_xy(0,5);
lcd_print("Af1 (s/s): ");
lcd_print(pm);
lcd_print_float(number);
strcpy(pm, " ");
End();
lcd_xy(35,7);
lcd_print(".....");
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x1C0D)
break;
}
}
}
void Disp_Cj()
{
int count = 0;
char array[2];
Init_Text(1);
lcd_xy(0,0);
while(bufferin != bufferout)
{
array[0] = char(Buffer());
if(count == 0)
{
if(array[0] == 0x0D)
{}
else if(array[0] == 0x0A)
{
count++;
}
}
else
{
if(array[0] == 0x0D)
{}
else if(array[0] == 0x0A)
{
if(count == 3)
{
lcd_xy(17,count - 1);
lcd_print(" / ");
count++;
}
else if(count < 3)
{
lcd_xy(0,count);
count++;
}
else
{
lcd_xy(0,count - 1);
count++;
}
}
else
lcd_print(array);
}
}
Init_Text(1);
//data
Disp_Ac(1);
//time
Disp_Aa(1);
for(i = 0; i < 4; i++)
byte = Buffer();
//lattitude
Disp_Ad(1);
//longitude
Disp_Ae(1);
//height
Disp_Af(1);
for(i = 0; i < 4; i++)
byte = Buffer();
//velocity
velocity = Bytes(1);
lcd_xy(7,3); //first character, 1 line
lcd_print("Velocity (m/s): ");
lcd_print_float(velocity / 100);
heading = Bytes(1);
lcd_xy(7,4); //first character, 1 line
lcd_print("Current Heading: ");
lcd_print_float(heading / 100);
dput(0x80); //write character(degree sign)
cput(0xc0); //increment memory ptr.
//geometry
dop = Bytes(1);
if(dop == 0)
{
lcd_xy(6,5); //first character, 1 line
lcd_print("Current DOP not computable.");
}
else
{
lcd_xy(7,5); //first character, 1 line
lcd_print("Current DOP: ");
lcd_print_float(dop / 10);
}
byte = Buffer();
lcd_xy(4,6); //first character, 1 line
if(byte == 0)
lcd_print("DOP Type: PDOP(3D)/Antenna Ok.");
else if(byte == 1)
lcd_print("DOP Type: HDOP(2D)/Antenna Ok.");
else if(byte == 64)
lcd_print("DOP Type: PDOP(3D)/Antenna shorted.");
else if(byte == 65)
lcd_print("DOP Type: HDOP(3D)/Antenna shorted.");
else if(byte == 128)
lcd_print("DOP Type: PDOP(3D)/Antenna open.");
else if(byte == 129)
lcd_print("DOP Type: PDOP(3D)/Antenna open.");
else if(byte == 192)
lcd_print("DOP Type: PDOP(3D)/Antenna shorted.");
else if(byte == 193)
lcd_print("DOP Type: PDOP(3D)/Antenna shorted.");
if(flag == 1)
{
lcd_xy(35,7);
lcd_print(".....");
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x1C0D)
break;
}
//Satellite visibility
Init_Text(1);
lcd_xy(5,2);
lcd_print("Num of visible satellites: ");
lcd_print_num(Buffer(),0);
lcd_xy(5,3);
lcd_print("Num of satellites tracked: ");
lcd_print_num(Buffer(),0);
lcd_xy(35,7);
lcd_print(".....");
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x1C0D)
break;
}
byte = Buffer();
lcd_xy(0,1);
lcd_print("Channel Tracking Mode: ");
lcd_xy(3,2);
lcd_print(channel[byte]);
lcd_xy(0,3);
lcd_print("Carrier to Noise Density Ratio: ");
lcd_print_num(Buffer(),0);
lcd_print("dB-Hz");
byte = Buffer();
lcd_xy(0,4);
lcd_print("Channel Status Flag: ");
else
{
lcd_xy(1,5 + count);
lcd_print(ch_status[j]);
count++;
}
}
}
if(count == 0)
lcd_print("0");
count = 0;
while(1)
{
key = _bios_keybrd(_KEYBRD_READ);
if(key == 0x1C0D)
break;
}
}
//Receiver status flag
Init_Text(1);
lcd_xy(5,2);
lcd_print("Receiver status flag: ");
byte = Buffer();
count = 0;
for(j = 0; j < 8; j++)
{
num = (byte >> j) & 0x01;
if(num == 1 && j != 2)
{
lcd_xy(6,3 + count);
lcd_print(re_status[j]);
count++;
}
}
byte = 1;
}//end of flag == 1
else if((flag == 0) || (flag == 2))
{
for(i = 0; i < 35; i++)
byte = Buffer();
byte = 0;
}
End();
return byte;
}
void Disp_Fa()
{
int i, num, count = 0;
int bit14 = 0, bit15 = 0;
Init_Text(1);
if(count == 16)
{
lcd_xy(7,3);
lcd_print("Selftest Passed!!!");
}
End();
}
End();
}
FILE: PIC.H
int Gps_pic_less[963] = {
1054, 0x1f, 0x80, 0x07, 0x80, 1025, 0x01, 0xff
0xf8, 0x03, 0xc0, 1006, 0x0f, 0xf8, 1006, 0x0f
0xf8, 1009, 0x7e, 0x00, 0x07, 0xe3, 0x7c, 1006
0x7f, 0xff, 0x00, 0x03, 0xff, 0xff, 1002, 0x7f
0xff, 1008, 0x0f, 0xc0, 0x00, 0x01, 0xfe, 0x1f
0x80, 1004, 0x01, 0xff, 0xff, 0xc0, 0x03, 0xff
0xff, 0xe0, 0x01, 0xff, 0xff, 0x80, 1007, 0x18
1003, 0x03, 0x81, 0xc0, 1004, 0x03, 0xff, 0xff
0xe0, 0x03, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff
0xc0, 1007, 0x30, 0x00, 0x0f, 0x00, 0x01, 0xc1
0xc0, 1004, 0x07, 0xf8, 0x07, 0xf0, 0x03, 0xff
0xff, 0xf8, 0x03, 0xf0, 0x0f, 0xe0, 1006, 0x01
0xe3, 0xe0, 0x3f, 0xfe, 0x00, 0x78, 0xf0, 1004
0x0f, 0xc0, 0x01, 0xf8, 0x03, 0xc0, 0x00, 0xfc
0x07, 0xc0, 0x03, 0xf0, 1006, 0x03, 0x07, 0xe0
0x7f, 0xfe, 0x00, 0x0c, 0x38, 1004, 0x1f, 1002
0xf8, 0x03, 0xc0, 0x00, 0x7c, 0x0f, 0x80, 0x00
0xf0, 1006, 0x06, 0x1f, 0xc0, 0xff, 0xfe, 0x03
0x86, 0x1c, 1004, 0x1e, 1002, 0x7c, 0x03, 0xc0
0x00, 0x3e, 0x0f, 1002, 0xf8, 1006, 0x0c, 0x1e
0x18, 0x01, 0xfe, 0x03, 0x83, 0x0e, 1004, 0x3e
1002, 0x3c, 0x03, 0xc0, 0x00, 0x1e, 0x0f, 1002
0x78, 1006, 0x18, 0x03, 0xff, 0xff, 0xff, 0xff
0xc1, 0x87, 1004, 0x3c, 1002, 0x3c, 0x03, 0xc0
0x00, 0x1e, 0x0f, 1002, 0x78, 1006, 0x30, 0x03
0xff, 0xff, 0xff, 0xff, 0xc1, 0xc3, 0x80, 1003
Appendix F
Assembly Code
The assembly code consists of only one file: 'Oncore.as'. The assembly code implements exactly the same functions as the C++ code. Only the 'Almanac' and
'Vissible Satellite' commands are ommitted.
;Data Segment
dseg at 0008h ;data segment in Ram from 03h
org 08h
X0 equ 08h
X1 equ 09h
X2 equ 0ah
X3 equ 0bh
Y0 equ 0ch
Y1 equ 0dh
Y2 equ 0eh
Y3 equ 0fh
Z0 equ 10h
Z1 equ 11h
Z2 equ 12h
Z3 equ 13h
Z4 equ 14h
Z5 equ 15h
Z6 equ 16h
Z7 equ 17h
PR0 equ 18h
PR1 equ 19h
PR2 equ 1ah
PR3 equ 1bh
;/////////////////////////////////
;Xdata Segment
xseg at 00h ;switch to XDATA segment at address 0
org 00h
ringbuffer:
ds 230 ;gives 230 bytes
yebo:
ds 5
array:
ds 15
;////////////////////////////
;Code Segment
cseg at 0000h ;code segment in Rom from 0000h
reti
;//////////////////////////////////////
;Code starts here:
org 0050h
;//////////////////////////////////////
;Interrupt service routine serial
serial:
push acc
jnb TI,serial1
clr TI ;ignore transmit interrupts
serial1:
jnb RI,serialdone ;done if no receive interrupt
mov b,SBUF
clr RI ;clear serial status bit
;/////////////////////////////////////////////
;Interrupt service routine Pushbutton
Pushbutton:
lcall FindRow
mov b,a
jnc GetColumn
jmp Nothing
GetColumn:
lcall FindColumn
swap a
orl a,b
mov b,a
jnc ReportKey
jmp Nothing
ReportKey:
mov key,b
jmp StillKey
Nothing:
reti
StillKey:
lcall KeyRelease ;waiting for release
jc StillKey
mov P1,#0fh
clr EX0
reti
;///////////////////////////////////////////////
;Function FindRow
FindRow:
mov a,P1 ;rows in port 1
mov r0,#4 ;counter
TryNextRow:
rrc a
jnc RowFound
djnz r0,TryNextRow
setb C
ret
RowFound:
mov a,#4
subb a,r0
clr C
ret
;///////////////////////////////////////////////////
;Function FindColumn
FindColumn:
mov r0,#4
mov a,#0efh
push acc
TryNextColumn:
pop acc
mov P1,a
rl a
push acc
mov a,P1
orl a,#0f0h
cpl a
jnz ColumnFound
djnz r0,TryNextColumn
pop acc
setb C
mov P1,#0fh
ret
ColumnFound:
pop acc
mov a,#4
clr C
subb a,r0
clr C
mov P1,#0fh
ret
;/////////////////////////////////////////////////
;Function KeyRelease
KeyRelease:
mov P1,#0fh
mov a,P1
orl a,#0f0h
cpl a
jz NoKey
setb C
ret
NoKey:
clr C
ret
;///////////////////////////////////////////////
org 01a0h
Start:
using 0 ;using bank of registers 0
Initilisation:
;sets up stack pointer to 5fh as required.
mov SP,#(Stack-1)
mov IE,#00h ;disable all interrupts
mov P0,#00h ;P0: low, configured as output
;P1: columns low and rows high for keyboard routine
mov P1,#0fh
mov P2,#0f0h ;P2: low byte output
;/////////////////////////////////////////////
;Function Main: calls Gps and receives info back
;from Gps and displays it on LCD
main:
clr TI
clr RI
mov flag,#1
mov tag,#1
mov check,#1
mov count,#0
mov bufferin,#0
mov bufferout,#0
mov key,#0
mov num1,#0
mov num2,#0
mov num3,#0
lcall lcd_setup
lcall lcd_init
lcall Disp_Pic
DoWhile: ;do
jmp EndSwitch ;while(bufferin != bufferout)
BeginSwitch:
lcall Buffer ;index1 = Buffer()
lcall Buffer ;index2 = Buffer()
lcall Buffer ;index1 = Buffer()
mov index1,r3
lcall Buffer ;index2 = Buffer()
mov index2,r3
mov tag,#1
mov r4,#0
lcall Disp_Ae ;Disp_Ae(0)
jmp EndA ;break
Switch_A:
mov a,index2
add a,#159
jz Case_Aa
dec a
jz Case_Ab
dec a
jz Case_Ac
dec a
jz Case_Ad
dec a
jz Case_Ae
dec a
jz Case_Af
dec a
jz Case_Ag
add a,#246
jz Case_Aq
add a,#250
jz Case_Aw
jmp EndA
EndA:
jmp EndSwitch ;break
Switch_B:
mov a,index2
add a,#150
jz Case_Bj
jmp EndB
EndB:
jmp EndSwitch ;break
Switch_C:
mov a,index2
add a,#154
jz Case_Cf
jmp EndC
EndC:
jmp EndSwitch ;break
Switch_E:
mov a,index2
add a,#159
jz Case_Ea
jmp EndE
EndE:
jmp EndSwitch ;break
Switch_F:
mov a,index2
add a,#159
jz Case_Fa
jmp EndF
EndF:
jmp EndSwitch ;break
Switch_S:
mov a,index2
add a,#134
jz Case_Sz
jmp EndS
EndS:
jmp EndSwitch ;break
Main_Switch:
mov a,index1
add a,#191
jz F1
jmp F2
F1:
jmp BigA
F2:
dec a
jz F3
jmp F4
F3:
jmp BigB
F4:
dec a
jz BigC
add a,#254
jz BigE
dec a
jz BigF
add a,#243
jz BigS
jmp EndSwitch
EndSwitch:
mov a,bufferin
cjne a,bufferout,Back
jmp Next
Back:
jmp BeginSwitch
;////////////////////////////////////////
Next:
mov a,key
jz F5 ;if(key != 0)
jmp F6
F5:
setb EX0
jmp EndCommand
F6:
mov a,tag
cjne a,#1,Fail1 ;if(tag == 1)
mov a,key
cjne a,#23h,Fail1
mov key,#0
mov num1,#0 ;num1 = 0
mov tag,#0 ;tag = 0
jmp GoToCommands ;else if(tag == 0)
Fail1:
mov a,tag
jnz Fail2
lcall Key_Press_0 ;num1 = Key_Press_0()
mov num1,r3
setb EX0
jmp GoToCommands
Fail2:
setb EX0
mov num1,#5 ;num1 = 5 //else do nothing
GoToCommands:
jmp MainS ;switch(num1)
MainMenu: ;case 0:
lcall Main_Menu ;Main_Menu()
jmp EndCommand ;break
Pos_Sta_Dat: ;case 1:
lcall Sub_Menu1 ;Sub_Menu1()
lcall Key_Press_1 ;num2 = Key_Press_1()
mov num2,r3
U5:
jmp Switch_1
U4:
lcall lcd_clear_text ;lcd_clear_text()
mov r7,#148
lcall cput ;cput(0x94)
Switch_1: ;switch(num2)
jmp SwitchSub1
Pos_Status_Data: ;case 1:
lcall Pos_Menu ;Pos_Menu(check)
Pos_1: ;case 1:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#1
mov r5,#1
lcall Data_To_Gps ;Data_To_Gps()
U8: ;if(flag == 0)
mov a,flag
jnz U9
U9:
mov check,#1 ;check = 1
jmp EndPos ;break
Pos_2: ;case 2:
mov var3,#0
mov var2,#0
mov var1,#10
mov fl,#1
mov r5,#1
lcall Data_To_Gps ;Data_To_Gps()
U10:
mov a,count ;if(count == 1)
cjne a,#1,U11
jmp U12
U11:
jmp U13
U12:
mov count,#0 ;count = 0
U13:
mov flag,#0 ;flag = 0
mov check,#0 ;check = 0
jmp EndPos ;break
Pos_3: ;case 3:
mov var3,#0
mov var2,#0
mov var1,#20
mov fl,#1
mov r5,#1
lcall Data_To_Gps ;Data_To_Gps()
jmp U10
Pos_4: ;case 4:
mov var3,#0
mov var2,#0
mov var1,#30
mov fl,#1
mov r5,#1
lcall Data_To_Gps ;Data_To_Gps()
jmp U10
Pos:
mov a,num3
dec a
jz F7
jmp F8
F7:
jmp Pos_1
F8:
dec a
jz Pos_2
dec a
jz Pos_3
dec a
jz Pos_4
EndPos:
jmp EndPosition ;break
Lattitude: ;case 2:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#2
lcall Data_To_Gps ;Data_To_Gps()
jmp EndPosition ;break
Longitude: ;case 3:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#3
lcall Data_To_Gps ;Data_To_Gps()
jmp EndPosition ;break
Height: ;case 4:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#4
lcall Data_To_Gps ;Data_To_Gps()
jmp EndPosition ;break
Date: ;case 5:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#5
lcall Data_To_Gps ;Data_To_Gps()
jmp EndPosition ;break
Time_Of_Day: ;case 6:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#6
lcall Data_To_Gps ;Data_To_Gps()
jmp EndPosition ;break
SwitchSub1:
mov a,num2
dec a
jz F9
jmp F10
F9:
jmp Pos_Status_Data
F10:
dec a
jz Lattitude
dec a
jz Longitude
dec a
jz Height
dec a
jz Date
dec a
jz Time_Of_Day
EndPosition:
jmp EndCommand ;break
Gps_Modes: ;case 2:
lcall Sub_Menu2 ;Sub_Menu2()
mov r7,#148
lcall cput ;cput(0x94)
U18: ;switch(num2)
jmp SwitchSub2
Gmt: ;case 1:
lcall Gmt_Menu ;Gmt_Menu()
Gmt_Poll: ;case 1:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#7
lcall Data_To_Gps ;Data_To_Gps()
jmp EndGmt ;break
Gmt_Change: ;case 2:
lcall lcd_clear_text ;lcd_clear_text()
mov r7,#151
lcall cput ;cput(0x97)
mov fla,#0
lcall Numbers ;Numbers( 0 )
mov fla,#1
lcall Numbers ;Numbers( 1 )
mov r7,#151
lcall cput ;cput(0x97)
mov fla,#1
lcall Numbers ;Numbers( 1 )
U20:
mov var3,minutes
mov var2,hours
mov var1,sign
mov fl,#3
mov r5,#8
lcall Data_To_Gps ;Data_To_Gps()
jmp EndGmt ;break
GmtFind:
mov a,num3
dec a
jz F11
jmp F12
F11:
jmp Gmt_Poll
F12:
dec a
jz F13
jmp EndGmt
F13:
jmp Gmt_Change
EndGmt:
jmp EndModes ;break
Time_Mode: ;case 2:
lcall Time_Menu ;Time_Menu()
Time_Mode_Poll: ;case 1:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#9
Time_Mode_Change: ;case 2:
lcall Time_Change ;Time_Change()
mov var3,#0
mov var2,#0
mov var1,time
mov fl,#1
mov r5,#10
lcall Data_To_Gps ;Data_To_Gps()
jmp EndTime ;break
TimeFind:
mov a,num3
dec a
jz Time_Mode_Poll
dec a
jz Time_Mode_Change
EndTime:
jmp EndModes ;break
Leap_Second: ;case 3:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#1
mov r5,#11
lcall Data_To_Gps ;Data_To_Gps()
jmp EndModes ;break
Atmosphere: ;case 4:
lcall Atmos_Menu ;Atmos_Menu()
Atmosphere_Poll: ;case 1:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#12
lcall Data_To_Gps ;Data_To_Gps()
Atmosphere_Change: ;case 2:
lcall Atmos_Sub_Menu ;Atmos_Sub_Menu()
mov var3,#0
mov var2,#0
mov var1,atmos
mov fl,#1
mov r5,#13
lcall Data_To_Gps ;Data_To_Gps()
jmp EndAtmos ;break
AtmosFind:
mov a,num3
dec a
jz Atmosphere_Poll
dec a
jz Atmosphere_Change
EndAtmos:
jmp EndModes ;break
Satellite_Mask: ;case 5:
lcall Mask_Menu ;Mask_Menu()
Mask_Poll: ;case 1:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#14
lcall Data_To_Gps ;Data_To_Gps()
jmp EndMask ;break
Mask_Change: ;case 2:
lcall Mask_Sub_Menu ;Mask_Sub_Menu()
mov fla,#1
lcall Numbers ;Numbers( 1 )
mov var3,#0
mov var2,#0
mov var1,angle
mov fl,#1
mov r5,#15
lcall Data_To_Gps ;Data_To_Gps()
jmp EndMask ;break
Sat_Find:
mov a,num3
dec a
jz Mask_Poll
dec a
jz Mask_Change
EndMask:
jmp EndModes ;break
SwitchSub2:
mov a,num2
dec a
jz F15
jmp F16
F15:
jmp Gmt
F16:
dec a
jz F17
jmp F18
F17:
jmp Time_Mode
F18:
dec a
jz F19
jmp F20
F19:
jmp Leap_Second
F20:
dec a
jz F21
jmp F22
F21:
jmp Atmosphere
F22:
dec a
jz F23
jmp F24
F23:
jmp Satellite_Mask
F24:
EndModes:
jmp EndCommand ;break
Receiver_Func: ;case 3:
mov r7,#148
lcall cput ;cput(0x94)
U31: ;switch(num2)
jmp SwitchSub3
Gps_Selftest: ;case 2:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#16
lcall Data_To_Gps ;Data_To_Gps()
jmp EndFunc ;break
Gps_Set_Defaults: ;case 3:
mov var3,#0
mov var2,#0
mov var1,#0
mov fl,#0
mov r5,#17
lcall Data_To_Gps ;Data_To_Gps()
jmp EndFunc ;break
SwitchSub3:
mov a,num2
dec a
jz Gps_Selftest
dec a
jz Gps_Set_Defaults
EndFunc:
jmp EndCommand ;break
MainS:
mov a,num1
jz F25
jmp F26
F25:
jmp MainMenu
F26:
dec a
jz F27
jmp F28
F27:
jmp Pos_Sta_Dat
F28:
dec a
jz F29
jmp F30
F29:
jmp Gps_Modes
F30:
dec a
jz F31
jmp F32
F31:
jmp Receiver_Func
F32:
EndCommand:
mov P1,#0fh
mov key,#0
mov a,num1
cjne a,#4,StartAgain ;while(num1 != 4)
jmp EndMain
StartAgain:
jmp DoWhile
EndMain:
mov r7,#152
lcall cput ;cput(0x98)
jmp Final
;//////////////////////////////////////////////
;Functions for Control signals
WRHI:
setb p2.0
ret
WRLO:
clr p2.0
ret
RDHI:
setb p2.1
ret
RDLO:
clr p2.1
ret
CEHI:
setb p2.2
ret
CELO:
clr p2.2
ret
CDHI:
setb p2.3
ret
CDLO:
clr p2.3
ret
;/////////////////////////////////////////////////
;Function lcd_clear_test
lcd_clear_text:
mov r7,#0d
lcall dput
mov r7,#0d
lcall dput
mov r7,#36d
lcall cput
clr a
mov i+0,a ;clear i
mov i+1,a
jmp Test
Loop:
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
inc i+1
mov a,i+1
jnz Bypass
inc i+0
Bypass:
Test:
mov a,i+1
add a,#low -(320)
mov a,i+0
xrl a,#80h
addc a,#(high -(320))xor 80h
jnc Loop
ret
;////////////////////////////////////////////////
;Function lcd_print
lcd_print:
prtLCD:
pop dph ; pop return address into dptr
pop dpl
prtNext:
clr a ; set offset = 0
movc a,@a+dptr ; get chr from code memory
cjne a,#0, chrOK ; if chr = 0 then return
sjmp retPrtLCD
chrOK:
subb a,#20h
mov r7, a
lcall wrLCDdata ; send character
inc dptr ; point at next character
ljmp prtNext ; loop till end of string
retPrtLCD:
mov a, #1h ; point to instruction after string
jmp @a+dptr ; return with a jump instruction
;////////////////////////////////////////////
lcd_print1:
clr a ; set offset = 0
movc a,@a+dptr ; get chr from code memory
mov univ,a
mov a,#1 ; set offset = 0
movc a,@a+dptr ; get chr from code memory
mov dpl,a
mov a,univ
mov dph,a
printNext:
clr a ; set offset = 0
movc a,@a+dptr ; get chr from code memory
cjne a,#0, char_is_OK ; if chr = 0 then return
sjmp returnPrtLCD
char_is_OK:
subb a,#20h
mov r7, a
lcall wrLCDdata ; send character
inc dptr ; point at next character
ljmp printNext ; loop till end of string
returnPrtLCD:
ret
;//////////////////////////////////////////////////
;Function wrLCDdata: prints out characters
wrLCDdata:
lcall dput
mov r7,#192d
lcall cput
ret
;//////////////////////////////////////////////
;Function lcd_xy: place cursor at x/y position
lcd_xy:
mov y,r2 ;y == 0
mov y+1,r3
mov x,r4 ;x == 0
mov x+1,r5
mov r4,#high (40) ;Bytes_Per_Row = 40
mov r5,#low (40)
mov r2,y
mov r3,y+1
lcall mult8_8
mov a,r3
add a,x+1
mov address+1,a
mov a,r2
addc a,x
mov address,a
mov r4,address
mov r5,address+1
anl 4+0,#high (0FFh)
anl 5+0,#low (0FFh)
mov r7,1+4+0
lcall dput
mov r5,address
mov r4,#0
mov r7,1+4+0
lcall dput
mov r7,#36d
lcall cput
ret
;///////////////////////////////////////////////
;Function lcd_setup
lcd_setup:
lcall CEHI
lcall RDHI
lcall WRHI
lcall CDHI
ret
;////////////////////////////////////////////////
;Function lcd_init
lcd_init:
mov r7,#0d
lcall dput
mov r7,#2d
lcall dput
mov r7,#66d
lcall cput
mov r7,#40d
lcall dput
mov r7,#0d
lcall dput
mov r7,#67d
lcall cput
mov r7,#0d
lcall dput
mov r7,#0d
lcall dput
mov r7,#64d
lcall cput
mov r7,#40d
lcall dput
mov r7,#0d
lcall dput
mov r7,#65d
lcall cput
mov r7,#128d
lcall cput
mov r7,#167d
lcall cput
mov r7,#0d
lcall dput
mov r7,#0d
lcall dput
mov r7,#33d
lcall cput
mov r7,#0d
lcall dput
mov r7,#34d
lcall cput
mov r7,#0d
lcall dput
mov r7,#28d
lcall dput
mov r7,#36d
lcall cput
mov r7,#28d
lcall dput
mov r7,#192d
lcall cput
mov r7,#20d
lcall dput
mov r7,#192d
lcall cput
mov r7,#28d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#34d
lcall cput
mov r7,#08h
lcall dput
mov r7,#1ch
lcall dput
mov r7,#36d
lcall cput
mov r7,#10h
lcall dput
mov r7,#192d
lcall cput
mov r7,#10h
lcall dput
mov r7,#192d
lcall cput
mov r7,#10h
lcall dput
mov r7,#192d
lcall cput
mov r7,#0
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
mov r7,#0d
lcall dput
mov r7,#192d
lcall cput
ret
;//////////////////////////////////////////////////////
;Function sget
sget:
mov P0,#0ffh
lcall CDHI
lcall RDLO
lcall CELO
mov a,P0
lcall CEHI
lcall RDHI
ret
;/////////////////////////////////////////////////
;Function dput
dput:
lcall sget
anl a,#03h
cjne a,#03h,dput
mov P0,r7
lcall CDLO
lcall WRLO
lcall RDHI
lcall CELO
lcall CEHI
lcall WRHI
ret
;/////////////////////////////////////////////////
;Function cput
cput:
lcall sget
anl a,#03h
cjne a,#03h,cput
mov P0,r7
lcall CDHI
lcall RDHI
lcall WRLO
lcall CELO
lcall CEHI
lcall WRHI
ret
;//////////////////////////////////////////
;Function lcd_clear_graph
lcd_clear_graph:
mov r7,#0
lcall dput ; dput(0x0200%256)
mov r7,#2
lcall dput ;dput(0x0200>>8)
mov r7,#36
lcall cput ;cput(0x24)
mov r7,#192
lcall cput ;cput(0xc0)
inc i+1
mov a,i+1
jnz CC1
inc i
CC1:
mov a,i+1
add a,#low -(2560)
mov a,i
xrl a,#80h
addc a,#(high -(2560))xor 80h
jnc CC2
ret
;/////////////////////////////////////////
;Function lcd_setpixel
;param column assigned to r4 on entry
;param row assigned to r2 on entry
lcd_setpixel:
mov row,r2 ;address = 0x0200 + (row * 40) + (column / 6)
mov column,r4
mov a,r3
add a,#low(512)
mov address+1,a
mov a,r2
addc a,#high(512)
mov address,a
mov X3,#0
mov X2,#0
mov X1,#0
mov X0,column
mov Y0,#6
mov Y1,#0
mov Y2,#0
mov Y3,#0
lcall DIV32 ;Z4-Qlow - Z7-Qhigh / Z0-rem(low)
mov column,Z0
mov a,Z4
add a,address+1
mov address+1,a
mov a,Z5
addc a,address
mov address,a
mov r4,address
mov r5,address+1
anl 4+0,#high (0FFh)
anl 5+0,#low (0FFh)
mov a,r5
mov r7,a
lcall dput ;dput(addr%256)
mov r7,address
lcall dput ; dput(addr>>8)
mov r7,#36
lcall cput ;cput(0x24)
mov a,#05h
clr c
subb a,column
mov r7,a
orl 7,#0f8h
lcall cput ;cput(0xf8 | (5 - (column % 6)) )
ret
;//////////////////////////////////////////////
;Function Disp_Pic
;no - > index1
;num -> x
;counter -> y
;j -> time
;i -> index2
;k -> i
Disp_Pic:
mov index2,#0
mov time,#0
mov y,#0
mov y+1,#0
mov r7,#152
lcall cput ;cput(0x98)
lcall ADD16
clr a
movc a,@a+dptr
mov x,a
inc r2
lcall ADD16
clr a
movc a,@a+dptr
mov x+1,a
anl a,#080h
mov index1,a
mov r0,x ;num <<= 1
mov r1,x+1
mov a,r1
add a,r1
mov r1,a
mov a,r0
addc a,r0
mov r0,a
mov x,r0
mov x+1,r1
CC22:
inc y+1 ;counter++
mov a,y+1
jnz CC3
inc y
CC3:
jmp CC4
CC25:
ret
;//////////////////////////////////////////////
;Function Init_Text
Init_Text:
lcall lcd_clear_text
mov r7,#151
lcall cput
jmp q ;jump to end of function ;else if(f == 1)
middle:
mov r7,#148
lcall cput
q:
ret
;/////////////////////////////////////////////////
;Function Cursor_Pos
Cursor_Pos:
gg:
mov lines,l
dd:
mov chars,car
mov r7,chars
lcall dput
mov r7,lines
lcall dput
mov r7,#33
lcall cput
ret
;/////////////////////////////////////////////
;Function Main_Menu
Main_Menu:
mov f,#0
lcall Init_Text
mov car,#7
mov l,#3
lcall Cursor_Pos
lcall lcd_print
db "Main Menu to operate the GPS Oncore.",0
lcall lcd_print
db "Press ESC to quit!!",0
lcall lcd_print
db "POSITION/STATUS/DATA:",0
lcall lcd_print
db "GPS MODES:",0
lcall lcd_print
db "RECEIVER FUNCTIONS:",0
ret
;//////////////////////////////////////////////////
;Function Sub_Menu1
Sub_Menu1:
mov f,#0
lcall Init_Text
mov car,#7
mov l,#1
lcall Cursor_Pos
lcall lcd_print
db "POS/STATUS/DATA:",0
lcall lcd_print
db "LATTITUDE:",0
lcall lcd_print
db "LONGITUDE:",0
lcall lcd_print
db "HEIGHT:",0
lcall lcd_print
db "DATE:",0
lcall lcd_print
db "TIME OF DAY:",0
ret
;//////////////////////////////////////////////////
;Function Sub_Menu2
Sub_Menu2:
mov f,#0
lcall Init_Text
mov car,#7
mov l,#1
lcall Cursor_Pos
lcall lcd_print
db "GMT OFFSET:",0
lcall lcd_print
db "TIME MODE:",0
lcall lcd_print
db "LEAP SECOND PENDING STATUS:",0
lcall lcd_print
db "ATMOSPHERE CORRECTION MODE:",0
lcall lcd_print
db "SATELLITE MASK ANGLE:",0
ret
;//////////////////////////////////////////////////////
;Function Sub_Menu3
Sub_Menu3:
lcall Same_XY1
lcall lcd_print
db "GPS SELFTEST:",0
lcall Same_XY2
lcall lcd_print
db "SET TO DEFAULTS:",0
ret
;/////////////////////////////////////////////////////
;Function Pos_Menu
Pos_Menu:
mov f,#0
lcall Init_Text
mov car,#1
mov l,#1
lcall Cursor_Pos
lcall lcd_print
db "Poll Position once every 10 seconds: ",0
lcall lcd_print
db "Poll Position once every 20 seconds: ",0
lcall lcd_print
db "Poll Position once every 30 seconds: ",0
ret
;////////////////////////////////////////////////////
;Function Same_XY1
Same_XY1:
mov f,#0
lcall Init_Text
mov car,#1
mov l,#3
lcall Cursor_Pos
ret
;//////////////////////////////////////////////////////
;Function Same_XY2
Same_XY2:
mov r2,#high (4)
mov r3,#low (4)
mov r4,#high (2)
mov r5,#low (2)
lcall lcd_xy
ret
;/////////////////////////////////////////////////////////
;Function Gmt_Menu
Gmt_Menu:
lcall Same_XY1
lcall lcd_print
db "Poll current GMT Offset:",0
lcall Same_XY2
lcall lcd_print
db "Change current GMT Offset:",0
ret
;//////////////////////////////////////////////////////
;Function Time_Menu
Time_Menu:
lcall Same_XY1
lcall lcd_print
db "Poll current Time Mode:",0
lcall Same_XY2
lcall lcd_print
db "Change current Time Mode:",0
ret
;/////////////////////////////////////////////////////
;Function Time_Change
Time_Change:
lcall Same_XY1
lcall lcd_print
db "GPS Time:",0
lcall Same_XY2
lcall lcd_print
db "UTC Time:",0
ret
;/////////////////////////////////////////////////////
;Function Atmos_Menu
Atmos_Menu:
lcall Same_XY1
lcall lcd_print
db "Poll Atmosphere Correction Mode:",0
lcall Same_XY2
lcall lcd_print
db "Change Atmosphere Correction Mode:",0
ret
;///////////////////////////////////////////////////////////
;Function Atmos_Sub_Menu
Atmos_Sub_Menu:
mov f,#0
lcall Init_Text
mov car,#1
mov l,#1
lcall Cursor_Pos
lcall lcd_print
db "Ionospheric Model disabled:",0
lcall lcd_print
db "Ionospheric Model only enabled:",0
lcall lcd_print
db "Tropospheric Model only enabled:",0
lcall lcd_print
db "Both Models enabled:",0
ret
;////////////////////////////////////////////////////////////
;Function Mask_Menu
Mask_Menu:
lcall Same_XY1
lcall lcd_print
db "Poll current Satellite Mask Angle:",0
lcall Same_XY2
lcall lcd_print
db "Change current Satellite Mask Angle:",0
ret
;////////////////////////////////////////////////////////
;Function Mask_Sub_Menu
Mask_Sub_Menu:
mov f,#0
lcall Init_Text
lcall lcd_print
db "Enter angle in degrees( 0 - 89 ):",0
ret
;/////////////////////////////////////////////////////
; ====================================================
; subroutine mdelay - millisecond delay
; delays for 998 microseconds - 2 microseconds are
; reserved for the call to this routine.
; input : none
; output : none
; destroys : nothing - uses a
; ----------------------------------------------------
; 100h-a6h=5ah=(90)decimal
; 90 * 11 = 990
; plus 8 gives 998 microseconds
;
; microseconds (cycles)
; -----------------------
mdelay:
push acc ; 2
mov a, #0a6h ; 1
md_olp:
inc a ; 1 \
nop ; 1 |
nop ; 1 |
nop ; 1 |
nop ; 1 |
nop ; 1 |- 11 cycles
nop ; 1 |
nop ; 1 |
nop ; 1 |
jnz md_olp ; 2 /
nop ; 1
pop acc ; 2
ret ; 2
;////////////////////////////////////////////////////
;Function Gps_Chars
Gps_Chars:
sendGPS:
pop dph ;pop return address into dptr
pop dpl
mov j,#0
sendNext:
clr a ; set offset = 0
movc a,@a+dptr ; get chr from code memory
cjne a,#0,charOK ; if chr = 0 then return
sjmp retsendGPS
charOK:
mov r0,a
lcall sendGPSdata ; send character
inc dptr ; point at next character
inc j
mov a,j
dec a
jz D1
dec a
jz D1
dec a
jz D2
jmp D3
D1:
ljmp sendNext ; loop till end of string
D2:
mov checksum,r0
ljmp sendNext ; loop till end of string
D3:
mov a,r0
xrl checksum,a
ljmp sendNext ; loop till end of string
retsendGPS:
mov a, #1h ; point to instruction after string
jmp @a+dptr ;return with a jump instruction
;////////////////////////////////////////////////////
;Function sendGPSdata: sends out characters
sendGPSdata:
clr TI
mov SBUF,r0
lcall mdelay
ret
;/////////////////////////////////////////////////
;Function Data_To_Gps
Data_To_Gps:
mov a,r5
dec a
jz C1
jmp C2
C1:
jmp Possi
C2:
dec a
jz C3
jmp C4
C3:
jmp Lat
C4:
dec a
jz C5
jmp C6
C5:
jmp Lon
C6:
dec a
jz C7
jmp C8
C7:
jmp Hei
C8:
dec a
jz C9
jmp C10
C9:
jmp Datum
C10:
dec a
jz C11
jmp C12
C11:
jmp Tim
C12:
dec a
jz C13
jmp C14
C13:
jmp GmtP
C14:
dec a
jz C15
jmp C16
C15:
jmp GmtC
C16:
dec a
jz C17
jmp C18
C17:
jmp TPoll
C18:
dec a
jz C19
jmp C20
C19:
jmp TChange
C20:
dec a
jz C21
jmp C22
C21:
jmp LeapS
C22:
dec a
jz C23
jmp C24
C23:
jmp AtmosP
C24:
dec a
jz C25
jmp C26
C25:
jmp AtmosC
C26:
dec a
jz C27
jmp C28
C27:
jmp MaskP
C28:
dec a
jz C29
jmp C30
C29:
jmp MaskC
C30:
dec a
jz C31
jmp C32
C31:
jmp Self
C32:
dec a
jz C33
jmp C34
C33:
jmp Defa
C34:
jmp lastchars
Possi:
lcall Gps_Chars
db "@@Ea",0
jmp lastchars
Lat:
lcall Gps_Chars
db "@@Ad",99h,99h,99h,99h,0
jmp lastchars
Lon:
lcall Gps_Chars
db "@@Ae",99h,99h,99h,99h,0
jmp lastchars
Hei:
lcall Gps_Chars
db "@@Af",99h,99h,99h,99h,99h,0
jmp lastchars
Datum:
lcall Gps_Chars
db "@@Ac",0ffh,0ffh,0ffh,0ffh,0
jmp lastchars
Tim:
lcall Gps_Chars
db "@@Aa",0ffh,0ffh,0ffh,0
jmp lastchars
GmtP:
lcall Gps_Chars
db "@@Ab",0ffh,0ffh,0ffh,0
jmp lastchars
GmtC:
lcall Gps_Chars
db "@@Ab",0
jmp lastchars
TPoll:
lcall Gps_Chars
db "@@Aw",0ffh,0
jmp lastchars
TChange:
lcall Gps_Chars
db "@@Aw",0
jmp lastchars
LeapS:
lcall Gps_Chars
db "@@Bj",0
jmp lastchars
AtmosP:
lcall Gps_Chars
db "@@Aq",0ffh,0
jmp lastchars
AtmosC:
lcall Gps_Chars
db "@@Aq",0
jmp lastchars
MaskP:
lcall Gps_Chars
db "@@Ag",0ffh,0
jmp lastchars
MaskC:
lcall Gps_Chars
db "@@Ag",0
jmp lastchars
Self:
lcall Gps_Chars
db "@@Fa",0
jmp lastchars
Defa:
lcall Gps_Chars
db "@@Cf",0
jmp lastchars
lastchars:
mov a,var1
xrl checksum,a ;checksum ^= var1 ^ var2 ^ var3
mov a,var2
xrl checksum,a
mov a,var3
xrl checksum,a
;////////////////////////////////////////////////////////////
;Function Buffer
Buffer:
clr EX0
mov a,bufferout ;ch = buffer[bufferout]
add a,#ringbuffer
mov r1,a
movx a,@r1
mov ch,a
mov r6,#50
loooop:
lcall mdelay ;mdelay()
djnz r6,loooop
clr a ;bufferout = 0
mov bufferout,a
D16: ;return ch
mov r3,ch
setb EX0
ret
;///////////////////////////////////////////////////
;Function Bytes
Bytes:
clr a
mov lb,a
mov lb+1,a
mov lb+2,a
mov lb+3,a
mov i,a ;for(i = 0; i < num; i++)
jmp D17
D18:
mov a,i ;if(i == 0)
jnz D19
inc i
mov a,i
D17:
cjne a,num,D18
mov r4,lb+2
mov r5,lb+3
ret
;///////////////////////////////////////////////////////
;Function EndDisps
EndDisps:
lcall Buffer ;Buffer()
lcall Buffer ;Buffer()
lcall Buffer ;Buffer()
ret
;////////////////////////////////////////////////////////
;Function Numbers
Numbers:
mov car,#13
mov l,#5
lcall Cursor_Pos
;///////////////////////////////////////////////////////
;Function Key_Press_0
Key_Press_0:
M2: ;while(1)
mov a,key ;if(key == 0x03)
cjne a,#3,M3
jmp M4
M3:
jmp M5
M4:
mov lines,#6 ;lines = 6
jmp M6 ;break
;---------------------------------------
M5: ;else if(key == 0x13)
mov a,key
cjne a,#19,M7
jmp M8
M7:
jmp M9
M8:
jmp M6 ;break
;--------------------------------------------------------------------
M9: ;else if(key == 0x22)
mov a,key
cjne a,#34,M10
jmp M11
M10:
jmp M12
M11:
mov key,#0
mov a,lines ;if(lines > 3)
cjne a,#3,M13
jmp M14
M13:
mov car,chars
mov l,#-1
lcall Cursor_Pos ;Cursor_Pos(-1, chars)
jmp M15
mov l,#5
lcall Cursor_Pos ;Cursor_Pos(5, chars)
M15:
jmp M16
;-------------------------------------------
M12: ;else if(key == 0x32)
mov a,key
cjne a,#50,M17
jmp M18
M17:
jmp M16
M18:
mov key,#0
mov a,lines ;if(lines < 5)
cjne a,#5,M19
jmp M20
M19:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp M16
M20: ;else if(lines == 5)
mov car,chars
mov l,#3
lcall Cursor_Pos ;Cursor_Pos(3, chars)
;--------------------------------------------
M16:
setb EX0
jmp M2 ;back to while(1)
M6:
mov a,lines ;return (lines - 2)
clr c
subb a,#02h
mov r3,a
mov key,#0
setb EX0
ret
;///////////////////////////////////////////////////
;Function Key_Press_1
Key_Press_1:
N2: ;while(1)
mov a,key ;if(key == 0x03)
cjne a,#3,N3
jmp N4
N3:
jmp N5
N4:
mov lines,#10 ;lines = 6
jmp N6 ;break
;-----------------------------------------------
N5: ;else if(key == 0x13)
mov a,key
cjne a,#19,N7
jmp N8
N7:
jmp N9
N8:
jmp N6 ;break
;----------------------------------------------
N9: ;else if(key == 0x22)
mov a,key
cjne a,#34,N10
jmp N11
N10:
jmp N12
N11:
mov key,#0
mov a,lines ;if(lines > 1)
cjne a,#1,N13
jmp N14
N13:
mov car,chars
mov l,#-1
lcall Cursor_Pos ;Cursor_Pos(-1, chars)
jmp N15
N19:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp N16
N20: ;else if(lines == 6)
mov car,chars
mov l,#1
lcall Cursor_Pos ;Cursor_Pos(1, chars)
;-------------------------------------------------
N16:
setb EX0
N6:
mov r3,lines ;return (lines)
mov key,#0
setb EX0
ret
;//////////////////////////////////////////////////
;Function Key_Press_2
Key_Press_2:
;while(1)
mov a,key ;if(key == 0x03)
cjne a,#3,O3
jmp O4
O3:
jmp O5
O4:
mov lines,#6 ;lines = 6
jmp O6 ;break
;----------------------------------------------
O5: ;else if(key == 0x13)
mov a,key
cjne a,#19,O7
jmp O8
O7:
jmp O9
O8:
jmp O6 ;break
;-----------------------------------------------
O9: ;else if(key == 0x22)
mov a,key
cjne a,#34,O10
jmp O11
O10:
jmp O12
O11:
mov key,#0
mov a,lines ;if(lines > 1)
cjne a,#1,O13
jmp O14
O13:
mov car,chars
mov l,#-1
lcall Cursor_Pos ;Cursor_Pos(-1, chars)
jmp O15
O19:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp O16
O20: ;else if(lines == 5)
mov car,chars
mov l,#1
lcall Cursor_Pos ;Cursor_Pos(1, chars)
;-------------------------------------------------
O16:
setb EX0
jmp O2 ;back to while(1)
O6:
mov r3,lines ;return (lines)
mov key,#0
setb EX0
ret
;//////////////////////////////////////////////////////////
;Function Key_Press_3
Key_Press_3:
YY2: ;while(1)
mov a,key ;if(key == 0x03)
cjne a,#3,YY3
jmp YY4
YY3:
jmp YY5
YY4:
mov lines,#6 ;lines = 6
jmp Y6 ;break
;---------------------------------------------------
YY5: ;else if(key == 0x13)
mov a,key
cjne a,#19,Y7
jmp Y8
Y7:
jmp Y9
Y8:
jmp Y6 ;break
;-------------------------------------------------
Y19:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp Y16
Y20: ;else if(lines == 4)
mov car,chars
mov l,#1
lcall Cursor_Pos ;Cursor_Pos(1, chars)
;------------------------------------------------
Y16:
setb EX0
jmp YY2 ;back to while(1)
Y6:
mov r3,lines ;return (lines)
mov key,#0
setb EX0
ret
;/////////////////////////////////////////////////////
;Function Key_Press_4
Key_Press_4:
Q2: ;while(1)
mov a,key ;if(key == 0x03)
cjne a,#3,Q3
jmp Q4
Q3:
jmp Q5
Q4:
mov lines,#6 ;lines = 6
jmp Q6 ;break
;-----------------------------------------------
Q5: ;else if(key == 0x13)
mov a,key
cjne a,#19,Q7
jmp Q8
Q7:
jmp Q9
Q8:
jmp Q6 ;break
;------------------------------------------------
Q9: ;else if(key == 0x22)
mov a,key
cjne a,#34,Q10
jmp Q11
Q10:
jmp Q12
Q11:
mov key,#0
mov a,lines ;if(lines > 3)
cjne a,#3,Q13
jmp Q14
Q13:
mov car,chars
mov l,#-1
lcall Cursor_Pos ;Cursor_Pos(-1, chars)
jmp Q15
mov key,#0
mov a,lines ;if(lines < 4)
cjne a,#4,Q19
jmp Q20
Q19:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp Q16 ;else if(lines == 4)
mov car,chars
mov l,#3
lcall Cursor_Pos ;Cursor_Pos(3, chars)
;------------------------------------------------
Q16:
setb EX0
jmp Q2 ;back to while(1)
Q6:
mov a,lines ;return (lines - 2)
clr c
subb a,#02h
mov r3,a
mov key,#0
setb EX0
ret
;///////////////////////////////////////////////
;Function Key_Press_5
Key_Press_5:
ZZ5:
mov a,key ;if(key == 0x03)
cjne a,#3,ZZ6
jmp ZZ7
ZZ6:
jmp Z8
ZZ7:
mov s,#43 ;sign = '+'
jmp Z9 ;break
;----------------------------------------------
Z8: ;else if(key == 0x13)
mov a,key
cjne a,#19,Z10
jmp Z11
Z10:
jmp Z12
Z11:
jmp Z9 ;break
;------------------------------------------------
Z12: ;else if((key == 0x22) && (chars == 13))
mov a,key
cjne a,#34,Z13
jmp Z14
Z14:
mov a,chars
cjne a,#13,Z13
jmp Z15
Z15:
jmp Z16
Z13:
jmp Z17
Z16:
mov key,#0
mov a,lines ;if(lines > 5)
cjne a,#5,Z18
jmp Z19
Z18:
mov car,chars
mov l,#-1
lcall Cursor_Pos ;Cursor_Pos(-1, chars)
jmp Z20
Z19: ;else if(lines == 5)
mov car,chars
mov l,#6
lcall Cursor_Pos ;Cursor_Pos(6, chars)
Z20:
jmp Z21
;-------------------------------------------------
Z17: ;else if((key == 0x32) && (chars == 13))
mov a,key
cjne a,#50,Z22
jmp Z23
Z23:
mov a,chars
cjne a,#13,Z22
jmp Z24
Z24:
jmp Z25
Z22:
jmp Z21
Z25:
mov key,#0
mov a,lines ;if(lines < 6)
cjne a,#6,Z26
jmp Z27
Z26:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp Z21
Z27: ;else if(lines == 6)
mov car,chars
mov l,#5
lcall Cursor_Pos ;Cursor_Pos(5, chars)
Z21:
setb EX0
jmp ZZ5
Z9:
mov a,lines ;if(lines == 5)
cjne a,#5,Z28
jmp Z29
Z28:
jmp Z30
Z29:
mov s,#45 ;s = '-'
jmp Z31
Z30: ;else if(lines == 6)
mov a,lines
cjne a,#6,Z32
jmp Z33
Z32:
jmp Z31
Z33:
mov s,#43 ;s = '+'
Z31:
mov key,#0
setb EX0
ret
;/////////////////////////////////////////////////
;Function Key_Press_6
;use var1, var2, checksum
Key_Press_6:
mov var1,#0
mov var2,#0
mov checksum,#0
Z34: ;while(1)
Z35: ;while(1)
mov a,key ;if(key == 0x03)
cjne a,#3,Z36
jmp Z37
Z36:
jmp Z38
Z37:
mov var1,#0 ;var1 = 0
jmp Z39 ;break
;----------------------------------------------
Z38: ;else if(key == 0x13)
mov a,key
cjne a,#19,Z40
jmp Z41
Z40:
jmp Z42
Z41:
jmp Z39 ;break
;--------------------------------------------------
Z42: ;else if((key == 0x22) && (chars != 13))
mov a,key
cjne a,#34,Z43
jmp Z44
Z44:
mov a,chars
cjne a,#13,Z45
jmp Z43
Z45:
jmp Z46
Z43:
jmp Z47
Z46:
mov key,#0
mov a,lines ;if(lines > 4)
cjne a,#4,Z48
jmp Z49
Z48:
mov car,chars
mov l,#-1
lcall Cursor_Pos ;Cursor_Pos(-1, chars)
jmp Z50
Z49: ;else if(lines == 4)
mov car,chars
mov l,#6
lcall Cursor_Pos ;Cursor_Pos(6, chars)
Z50:
jmp Z51
;------------------------------------------------
Z47: ;else if((key == 0x32) && (chars != 13))
mov a,key
cjne a,#50,Z52
mov a,chars
cjne a,#13,Z53
jmp Z52
Z53:
jmp Z54
Z52:
jmp Z55
Z54:
mov key,#0
mov a,lines ;if(lines < 6)
cjne a,#6,Z56
jmp Z57
Z56:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp Z58
Z57: ;else if(lines == 6)
mov car,chars
mov l,#4
lcall Cursor_Pos ;Cursor_Pos(4, chars)
Z58:
jmp Z51
;-------------------------------------------------
Z55: ;else if((key == 0x22) && (chars == 13))
mov a,key
cjne a,#34,Z59
mov a,chars
cjne a,#13,Z59
jmp Z60
Z59:
jmp Z61
Z60:
mov key,#0
mov a,lines ;if(lines > 4)
cjne a,#4,Z62
jmp Z63
Z62:
mov car,chars
mov l,#-1
lcall Cursor_Pos ;Cursor_Pos(-1, chars)
jmp Z64
Z63: ;else if(lines == 4)
mov car,chars
mov l,#5
lcall Cursor_Pos ;Cursor_Pos(5, chars)
Z64:
jmp Z51
;--------------------------------------------------
Z61: ;else if((key == 0x32) && (chars == 13))
mov a,key
cjne a,#50,Z65
mov a,chars
cjne a,#13,Z65
jmp Z66
Z65:
jmp Z67
Z66:
mov key,#0
mov a,lines ;if(lines < 5)
cjne a,#5,Z68
jmp Z69
Z68:
mov car,chars
mov l,#10
lcall Cursor_Pos ;Cursor_Pos(10, chars)
jmp Z70
Z69: ;else if(lines == 5)
mov car,chars
mov l,#4
lcall Cursor_Pos ;Cursor_Pos(4, chars)
Z70:
jmp Z51
;-------------------------------------------------
Z67: ;else if((key == 0x02) && ((lines == 4) || (lines == 5)))
mov a,key
cjne a,#2,Z71
mov a,lines
cjne a,#4,Z72
jmp Z73
Z72:
mov a,lines
cjne a,#5,Z71
Z73:
jmp Z74
Z71:
jmp Z75
Z74:
mov key,#0
Z86:
jmp Z51
;------------------------------------------------
Z83: ;else if((key == 0x02) && (lines == 6))
mov a,key
cjne a,#2,Z87
mov a,lines
cjne a,#6,Z87
jmp Z88
Z87:
jmp Z89
Z88:
mov key,#0
mov a,chars ;if(chars > 16)
cjne a,#16,Z90
jmp Z91
Z90:
mov a,chars
clr c
subb a,#03h
mov car,a
mov l,lines
lcall Cursor_Pos ;Cursor_Pos(lines, chars - 3)
jmp Z92
Z91: ;else if(chars == 16)
mov car,#22
mov l,lines
lcall Cursor_Pos ;Cursor_Pos(lines, 22)
Z92:
jmp Z51
;-----------------------------------------------------
Z89: ;else if((key == 0x12) && (lines == 6))
mov a,key
cjne a,#18,Z93
mov a,lines
cjne a,#6,Z93
jmp Z94
Z93:
jmp Z51
Z94:
mov key,#0
mov a,chars ;if(chars < 22)
cjne a,#22,Z96
jmp Z97
Z96:
mov a,chars
add a,#03h
mov car,a
mov l,lines
lcall Cursor_Pos ;Cursor_Pos(lines, chars + 3)
jmp Z51
Z97: ;else if(chars == 22)
mov car,#16
mov l,lines
lcall Cursor_Pos ;Cursor_Pos(lines, 16)
Z51:
setb EX0
jmp Z35
;--------------------------------------------------------
Z39:
mov a,key ;if(key == 0x03)
cjne a,#3,Z99
jmp Z100
Z99:
jmp Z101
Z100:
mov var1,a ;var1 = 0
jmp Z102 ;break
;--------------------------------------------------------
Z101: ;else if(key == 0x13)
mov a,key
cjne a,#19,Z103
jmp Z104
Z103:
jmp Z105
Z104:
mov a,lines ;if((lines == 5) && (chars == 13))
cjne a,#5,Z106
mov a,chars
cjne a,#13,Z106
jmp Z107
Z106:
jmp Z108
Z107:
mov var2,#1 ;for(i = 1; i <= count; i++)
jmp Z109
Z110: ;var1 = var1 + yebo[i - 1] * pow(10,count - i)
mov a,checksum
clr c
subb a,var2
mov r5,a
jz Z111
mov a,#1
Z111:
mov b,#10d ;pow operation (value will never be
;greater then 100)
mul ab
cjne r5,#0,Gogo1
jmp Gogo2
Gogo1:
djnz r5,Z111
Gogo2:
jz Power
mov fl,a
jmp Correct
Power:
inc a
mov fl,a
Correct:
clr c
mov a,var2
subb a,#01h
mov r3,a
mov a,#yebo
add a,r3
mov r1,a
movx a,@r1 ;r4 contains now value from array
mov 4+0,a
mov a,r4
mov b,fl
mul ab
add a,var1
mov var1,a
inc var2
Z109:
clr c
mov a,checksum
subb a,var2
add a,#1
jnz Z110
jmp Z102
Z108: ;else
inc checksum ;var3++
;yebo[count - 1] = nums[lines - 4][chars - 13]
mov a,lines
clr c
subb a,#04h
mov b,#10
mul ab
mov r2,a
clr c
mov a,chars
subb a,#0dh
add a,r2
mov r2,a
mov a,checksum
clr c
subb a,#01h
mov r1,a
mov a,#yebo
add a,r1
mov r1,a
lcall GetVal
movx @r1,a
mov fl,a
mov r1,#0
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num(yebo[count - 1],0)
Z105:
setb EX0
mov key,#0
jmp Z34
Z102:
mov r3,var1 ;return var1
mov key,#0
setb EX0
ret
;////////////////////////////////////////////////
;Function GetVal
GetVal:
mov a,r2
inc a
movc a,@a+pc
ret
nums:
db 0
db 0
db 0
db 1
db 0
db 0
db 2
db 0
db 0
db 3
db 0
db 0
db 0
db 4
db 0
db 0
db 5
db 0
db 0
db 6
db 0
db 0
db 0
db 7
db 0
db 0
db 8
db 0
db 0
db 9
;////////////////////////////////////////////
;Function lcd_print_num
;count - num
;temp - x
;i - l
;f - car
lcd_print_num:
mov num,#0
mov r2,Z7
mov r3,Z6 ;num = num / 10
mov r4,Z5
mov r5,Z4
mov a,Z4
jnz K2 ;if(a == 0)
jmp K3 ;break
K2:
jmp K1
K3:
;if((f == 1) && (temp > 0) && (temp < 10))
mov a,car
cjne a,#1,K4
mov a,x+1
add a,#low -(1)
mov a,x
xrl a,#80h
addc a,#(high -(1))xor 80h
jnc K4
jmp K5
K4:
jmp K6
K5:
mov a,x+1
add a,#low -(10)
mov a,x
xrl a,#80h
addc a,#(high -(10))xor 80h
jc K6
jmp K7
K6:
jmp K8
K7:
mov a,#array ;array[num] = 16
add a,num
mov r1,a
mov a,#16
movx @r1,a
K11:
mov r7,a
lcall dput ;dput(a)
mov r7,#192
lcall cput ;cput(0xc0)
mov a,l
clr c
subb a,#01h
mov l,a
K9:
mov a,l
add a,#1
jnz K10
ret
;///////////////////////////////////////////////////
;=================================================
; subroutine DIV32
; 32-Bit Unsigned Division
;=================================================
DIV32:
mov a,Y3 ;get divisor high byte
orl a,Y2
orl a,Y1
orl a,Y0 ;OR with low bytes
jnz div32_OK ;divisor OK if not 0
setb OV ;else, overflow
ret
div32_OK:
mov PR3,X3 ;store dividend
mov PR2,X2
mov PR1,X1
mov PR0,X0
mov X3,#0 ;clear partial remainder
mov X2,#0
mov X1,#0
mov X0,#0
mov r6,#0
mov r5,#0
mov r4,#0
mov r3,#0 ;clear partial quotient
mov r7,#32 ;set loop count
div32_loop:
clr C ;clear carry flag
mov a,PR0 ;shift the highest bit of the dividend...
rlc a ;... into...
mov PR0,a
mov a,PR1
rlc a
mov PR1,a
mov a,PR2
rlc a
mov PR2,a
mov a,PR3
rlc a
mov PR3,a
rlc a
mov X3,a
djnz r7,div32_loop
;//////////////////////////////////////////////////
;==================================================
; subroutine SUB32
; 32-Bit Unsigned subtraction
;==================================================
SUB32:
mov a,X0 ;load X low byte into accumulator
clr C ;clear carry flag
subb a,Y0 ;subract Y low byte
mov Z0,a ;put result in Z low byte
mov a,X1 ;repeat with other bytes...
subb a,Y1
mov Z1,a
mov a,X2
subb a,Y2
mov Z2,a
mov a,X3
subb a,Y3
mov Z3,a
mov OV,C ;set ZOV id an external barrow is produced
ret ;done
;////////////////////////////////////////////////////
;===================================================
; subroutine ADD16
; 16-Bit Unsigned Addition
;===================================================
ADD16:
mov a,#low(Gps_pic_less); load X low byte into accumulator
add a,r2 ; add Y low byte
mov dpl,a ; put result in Z low byte
mov a,#high(Gps_pic_less); load X high byte into accumulator
addc a,r3 ; add Y high byte with the carry from low ...
; ... byte operation
mov dph,a ; save result in Z high byte
mov OV,C ; set OV if external carry
ret ; done
;/////////////////////////////////////////////////
;Function mult8_8: multiplies 2 8bit numbers
mult8_8:
mov a,r5
mov b,r3
mul ab
mov r3,a
push b
mov a,r5
mov b,r2
mul ab
pop 0
add a,r0
mov r2,a
ret
;//////////////////////////////////////////////
Disp_Aa:
mov univ,r4
mov a,r4
cjne a,#0,ww
mov f,#1
lcall Init_Text
lcall lcd_xy
lcall lcd_print
db "Current Time: ",0
jmp ww1
ww:
mov r2,#high (0)
mov r3,#low (0)
mov r4,#high (17)
mov r5,#low (17)
lcall lcd_xy
lcall lcd_print
db " / Time: ",0
ww1:
lcall Buffer
mov fl,r3
mov r1,#1
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db ":",0
lcall Buffer
mov fl,r3
mov r1,#1
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db ":",0
lcall Buffer
mov fl,r3
mov r1,#1
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db " hours",0
mov a,univ
cjne a,#0,ww2
lcall EndDisps
ww2:
ret
;//////////////////////////////////////////////////
Disp_Ab:
mov f,#1
lcall Init_Text
lcall lcd_print
db "GMT Offset: ",0
lcall Buffer
mov a,r3
cjne a,#0,ww3
lcall lcd_print
db "+",0
jmp ww4
ww3:
lcall lcd_print
db "-",0
ww4:
lcall Buffer
mov fl,r3
mov r1,#0
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db ":",0
lcall Buffer
mov fl,r3
mov r1,#0
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db "hours",0
lcall EndDisps
ret
;///////////////////////////////////////////////////
Disp_Ac:
mov univ,r4
mov a,r4
cjne a,#0,ww5
mov f,#1
lcall Init_Text
lcall lcd_print
db "Current Date(dd/mm/yyyy): ",0
jmp ww6
ww5:
mov r2,#high (0)
mov r3,#low (0)
mov r4,#high (0)
mov r5,#low (0)
lcall lcd_xy
lcall lcd_print
db "Date: ",0
ww6:
lcall Buffer
mov angle,r3
lcall Buffer
mov fl,r3
mov r1,#1
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db "/",0
mov r1,#1
mov r2,#high (0)
lcall lcd_print
db "/",0
mov num,#1
lcall Bytes ;r4 contains high byte
;r5 contains low byte
mov r1,#0
mov r2,#high (0)
mov r3,#low (0)
lcall lcd_print_num ;lcd_print_num()
mov a,univ
cjne a,#0,ww7
lcall EndDisps
ww7:
ret
;////////////////////////////////////////////////////
Disp_Ad:
mov univ,r4
mov a,r4
cjne a,#0,vv1
mov f,#1
lcall Init_Text
lcall lcd_print
db "Lattitude(milliarcseconds or mas): ",0
vv1:
mov num,#3
lcall Bytes ;r2 contains highest byte
;r3
;r4
;r5 contains lowest byte
mov lb,r2
mov lb+1,r3
mov lb+2,r4
mov lb+3,r5
mov a,univ
cjne a,#0,vv7
jmp vv8
vv7:
jmp vv2
vv8:
mov r2,#high (2)
mov r3,#low (2)
mov r4,#high (5)
mov r5,#low (5)
lcall lcd_xy
mov a,lb
anl a,#80h
cjne a,#80h,vv3 ;test if number is positive
lcall lcd_print
db "-",0
mov var1,#0
vv3:
lcall lcd_print
db "+",0
mov var1,#1
vv4:
mov r1,#0
mov r2,lb
mov r3,lb+1
mov r4,lb+2
mov r5,lb+3
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db "mas",0
lcall lcd_print
db "Lattitude(degrees/min/sec): ",0
jmp vv5
vv2:
mov r2,#high (1)
mov r3,#low (1)
mov r4,#high (0)
mov r5,#low (0)
lcall lcd_xy
lcall lcd_print
db "Position: ",0
vv5:
mov a,univ
cjne a,#0,vv6
mov r7,#80h
lcall dput ;dput(degree sign)
mov r7,#192
lcall cput
mov r7,#81h
lcall dput
mov r7,#192
lcall cput
mov r3,lb+3
lcall mult8_8
mov r7,#02h
lcall dput
mov r7,#192
lcall cput
mov a,var1
cjne a,#0,wert
lcall lcd_print
db "S",0
jmp wert1
wert:
lcall lcd_print
db "N",0
wert1:
mov a,univ
cjne a,#0,hhhh
lcall EndDisps
hhhh:
ret
;////////////////////////////////////////////////
Disp_Ae:
mov univ,r4
mov a,r4
cjne a,#0,qq1
mov f,#1
lcall Init_Text
lcall lcd_print
db "Longitude(milliarcseconds or mas): ",0
qq1:
mov num,#3
lcall Bytes ;r2 contains highest byte
;r3
;r4
;r5 contains lowest byte
mov lb,r2
mov lb+1,r3
mov lb+2,r4
mov lb+3,r5
mov a,univ
cjne a,#0,qq7
jmp qq8
qq7:
jmp qq2
qq8:
mov r2,#high (2)
mov r3,#low (2)
mov r4,#high (5)
mov r5,#low (5)
lcall lcd_xy
mov a,lb
anl a,#80h
cjne a,#80h,qq3 ;test if number is positive
lcall lcd_print
db "-",0
mov var1,#0
mov a,lb+3
cpl a
add a,#01h
mov lb+3,a
mov a,lb+2
cpl a
addc a,#0
mov lb+2,a
mov a,lb+1
cpl a
addc a,#0
mov lb+1,a
mov a,lb
cpl a
addc a,#0
mov lb,a
jmp ww4
qq3:
lcall lcd_print
db "+",0
mov var1,#1
qq4:
mov r1,#0 ;print angle
mov r2,lb
mov r3,lb+1
mov r4,lb+2
mov r5,lb+3
lcall lcd_print_num ;lcd_print_num()
lcall lcd_print
db "mas",0
lcall lcd_print
db "Longitude(degrees/min/sec): ",0
jmp qq5
qq2:
mov r2,#high (1)
mov r3,#low (1)
mov r4,#high (23)
mov r5,#low (23)
lcall lcd_xy
lcall lcd_print
db "/ ",0
qq5:
mov a,univ
cjne a,#0,qq6
mov X1,lb+2
mov X0,lb+3
mov Y0,#80h
mov Y1,#0eeh
mov Y2,#36h
mov Y3,#00h
lcall DIV32 ;Z4-Qlow - Z7-Qhigh / Z0-rem(low)
mov r7,#80h
lcall dput ;dput(degree sign)
mov r7,#192
lcall cput
mov lb+3,Z0
mov r7,#81h
lcall dput
mov r7,#192
lcall cput
mov r7,#02h
lcall dput
mov r7,#192
lcall cput
mov a,var1
cjne a,#0,wert2
lcall lcd_print
db "W",0
jmp wert3
wert2:
lcall lcd_print
db "E",0
wert3:
mov a,univ
cjne a,#0,gggg
lcall EndDisps
gggg:
ret
;/////////////////////////////////////////////////
Disp_Af:
mov univ,r4
mov a,r4
cjne a,#0,qq9
mov f,#1
lcall Init_Text
lcall lcd_print
db "Height(ellipsoid height in meters): ",0
jmp qq10
qq9:
mov r2,#high (2)
mov r3,#low (2)
mov r4,#high (7)
mov r5,#low (7)
lcall lcd_xy
lcall lcd_print
db "Height (m): ",0
qq10:
mov num,#3
lcall Bytes ;r2 contains highest byte
;r3
;r4
;r5 contains lowest byte
mov lb,r2
mov lb+1,r3
mov lb+2,r4
mov lb+3,r5
lcall lcd_print
db "m",0
mov a,univ
cjne a,#0,iiii
lcall EndDisps
iiii:
ret
;////////////////////////////////////////////////
Disp_Ag:
mov f,#1
lcall Init_Text
lcall lcd_print
db "Satellite Mask Angle (degrees): ",0
lcall Buffer
mov fl,r3
mov r1,#0
mov r2,#high (0)
mov r3,#low (0)
mov r4,high(fl)
mov r5,low(fl)
lcall lcd_print_num ;lcd_print_num()
mov r7,#192
lcall cput
lcall EndDisps
ret
;///////////////////////////////////////////////
Disp_Aq:
mov f,#1
lcall Init_Text
lcall lcd_print
db "Atmosphere Correction Mode: ",0
lcall Buffer
mov univ,r3
mov a,univ
cjne a,#0,ww8
lcall lcd_print
db "'0' = Ionosphere model disabled.",0
jmp ww11
ww8:
cjne a,#1,ww9
lcall lcd_print
db "'1' = Ionosphere model only enabled.",0
jmp ww11
ww9:
cjne a,#2,ww10
lcall lcd_print
db "'2' = Tropospheric model only enabled.",0
jmp ww11
ww10:
cjne a,#3,ww11
lcall lcd_print
db "'3' = Both models enabled.",0
ww11:
lcall EndDisps
ret
;////////////////////////////////////////////////
Disp_Aw:
mov f,#1
lcall Init_Text
lcall lcd_print
db "Current Time Mode: ",0
lcall Buffer
mov univ,r3
mov a,univ
cjne a,#0,ww12
lcall lcd_print
db "'0' = GPS Time.",0
jmp ww13
ww12:
cjne a,#1,ww13
lcall lcd_print
db "'1' = UTC Time.",0
ww13:
lcall EndDisps
ret
;/////////////////////////////////////////////////////
Disp_Bj:
mov f,#1
lcall Init_Text
lcall lcd_print
db "Leap Second Pending Status: ",0
lcall Buffer
mov univ,r3
mov a,univ
cjne a,#0,ww14
lcall lcd_print
db "'0' = No leap second pending.",0
jmp ww16
ww14:
cjne a,#1,ww15
lcall lcd_print
db "'1' = Addition of one second pending.",0
jmp ww16
ww15:
cjne a,#2,ww16
lcall lcd_print
db "'2' = Subtraction of one second pending.",0
ww16:
lcall EndDisps
ret
;////////////////////////////////////////////////
Disp_Fa:
mov var1,#0
mov row,#0
mov column,#0
mov f,#1
lcall Init_Text
lcall lcd_print
db "GPS Selftest Results: ",0
mov num,#1
lcall Bytes ;r4 contains high byte
mov r0,#aid1
mov a,r4
movx @r0,a
inc r0
mov a,r5
movx @r0,a
clr a
mov i,a
mov i+1,a
jmp ww19 ;for(i = 0; i < 16; i++)
ww20:
mov r5,i+1 ;num = (byte >> i) & 0x01
mov r0,#aid1
movx a,@r0
mov r2,a
inc r0
movx a,@r0
mov r3,a
cjne r5,#0,ww21
jmp ww22
ww21:
mov a,r2
clr c
rrc a
mov r2,a
mov a,r3
rrc a
mov r3,a
djnz r5,ww21
ww22:
mov a,r3
anl a,#01h
mov r0,#aid2
inc r0
movx @r0,a
dec r0
mov a,r2
anl a,#0
movx @r0,a
mov a,i+1
add a,i+1
mov r3,a
mov a,i
addc a,i
mov r2,a
mov a,r3
add a,#low(messages)
mov dpl,a
mov a,r2
addc a,#high(messages)
mov dph,a
lcall lcd_print1 ;lcd_print(messages[i])
jmp ww26
ww25: ;else if(num == 0)
mov r0,#aid2
inc r0
movx a,@r0
mov b,a
dec r0
movx a,@r0
orl a,b
jnz ww26
mov a,i+1
cjne a,#low (14),ww27
mov a,i
cjne a,#high (14),ww27
jmp ww29
ww27:
jmp ww30
ww29:
mov row,#1 ;bit14 = 1
jmp ww31
ww30: ;else if(num == 1 && i == 15)
mov r0,#aid2
inc r0
movx a,@r0
cjne a,#low (1),ww32
dec r0
movx a,@r0
cjne a,#high (1),ww32
mov a,i+1
cjne a,#low (15),ww32
mov a,i
cjne a,#high (15),ww32
jmp ww33
ww32:
jmp ww34
ww33:
mov column,#1 ; bit15 = 1
ww34:
ww31:
inc i+1
mov a,i+1
jnz ww19
inc i
ww19:
mov a,i+1
add a,#low -(16)
mov a,i
xrl a,#80h
addc a,#(high -(16))xor 80h
jnc ww44
jmp ww35
ww44:
jmp ww20
jmp ww42
ww41: ;else if(bit14 == 0 && bit15 == 1)
mov a,row
cjne a,#0,ww42
mov a,column
cjne a,#1,ww42
ww43: ;End()
lcall EndDisps
ret
;////////////////////////////////////////////////
Disp_Ea:
mov key,#0
mov var3,#0
mov f,#1
lcall Init_Text
mov r4,#1
lcall Disp_Ac ;date
mov r4,#1
lcall Disp_Aa ;time
mov r0,#4
ll1:
lcall Buffer
djnz r0,ll1
mov r4,#1
lcall Disp_Ad ;lattitude
mov r4,#1
lcall Disp_Ae ;longitude
mov r4,#1
lcall Disp_Af ;height
mov r0,#4
ll2:
lcall Buffer
djnz r0,ll2
mov lb,r4
mov lb+1,r5
lcall lcd_print
db "Velocity (m/s): ",0
mov lb,r4
mov lb+1,r5
lcall lcd_print
db "Current Heading: ",0
mov X0,lb+1
mov Y0,#64h
mov Y1,#00h
mov Y2,#00h
mov Y3,#00h
lcall DIV32 ;Z4-Qlow - Z7-Qhigh / Z0-rem(low)
mov r7,#80h
lcall dput
mov r7,#192
lcall cput
mov lb,r4
mov lb+1,r5
mov a,r5
orl a,r4
jnz ll3
lcall lcd_print
db "Current DOP not computable.",0
jmp hello
ll3:
mov r2,#high (5)
mov r3,#low (5)
mov r4,#high (7)
mov r5,#low (7)
lcall lcd_xy
lcall lcd_print
db "Current DOP: ",0
mov Y0,#0ah
mov Y1,#00h
mov Y2,#00h
mov Y3,#00h
lcall DIV32 ;Z4-Qlow - Z7-Qhigh / Z0-rem(low)
lcall Buffer
mov a,r3
cjne a,#0,ll4
lcall lcd_print
db "DOP Type: PDOP(3D)/Antenna OK.",0
jmp ll11
ll4:
cjne a,#1,ll5
lcall lcd_print
db "DOP Type: HDOP(2D)/Antenna OK.",0
jmp ll11
ll5:
cjne a,#64,ll6
lcall lcd_print
db "DOP Type: PDOP(3D)/Antenna shorted.",0
jmp ll11
ll6:
cjne a,#65,ll7
lcall lcd_print
db "DOP Type: HDOP(2D)/Antenna shorted.",0
jmp ll11
ll7:
cjne a,#128,ll8
lcall lcd_print
db "DOP Type: PDOP(3D)/Antenna open.",0
jmp ll11
ll8:
cjne a,#129,ll9
lcall lcd_print
db "DOP Type: HDOP(2D)/Antenna open.",0
jmp ll11
ll9:
cjne a,#192,ll10
lcall lcd_print
db "DOP Type: PDOP(3D)/Antenna shorted.",0
jmp ll11
ll10:
cjne a,#193,ll11
lcall lcd_print
db "DOP Type: HDOP(2D)/Antenna shorted.",0
ll11:
mov a,flag ;if flag == 1
cjne a,#1,ll12
jmp ll13
ll12:
jmp ll14
ll13:
mov r2,#high (7)
mov r3,#low (7)
mov r4,#high (35)
mov r5,#low (35)
lcall lcd_xy
lcall lcd_print
db ".....",0
mov f,#1
lcall Init_Text
lcall lcd_print
db "Num of visible satellites: ",0
lcall Buffer
mov a,r3
lcall lcd_print
db "Num of satellites tracked: ",0
lcall Buffer
mov a,r3
lcall lcd_print
db ".....",0
mov var1,#0
jmp ll17
ll18:
mov f,#1
lcall Init_Text
lcall lcd_print
db "Channel ",0
mov a,var1
add a,#1
lcall lcd_print
lcall Buffer
mov a,r3
lcall lcd_print
db "Channel Tracking Mode: ",0
lcall Buffer
mov a,r3
add a,r3
mov r3,a
mov a,#0
addc a,#0
mov r2,a
mov a,r3
add a,#low(channel)
mov dpl,a
mov a,r2
addc a,#high(channel)
mov dph,a
lcall lcd_print1 ;lcd_print(channel[byte])
lcall lcd_print
db "Carrier to Noise Density Ratio: ",0
lcall Buffer
mov a,r3
lcall lcd_print
db "dB-Hz",0
lcall lcd_print
db "Channel Status Flag: ",0
lcall Buffer
mov lb,r3
mov var2,#0
jmp ll19
ll20:
mov r5,var2 ;num = (byte >> i) & 0x01
mov r0,#0
mov r1,lb
cjne r5,#0,ll21
jmp ll22
ll21:
mov a,r0
clr c
rrc a
mov r0,a
mov a,r1
rrc a
mov r1,a
djnz r5,ll21
ll22:
mov a,r1
anl a,#01h
cjne a,#1,ll23
jmp ll24
ll23:
jmp ll25
ll24:
mov a,var2
cjne a,#1,ll26
jmp ll25
ll26:
cjne a,#2,ll27
jmp ll25
ll27:
mov a,#5
add a,var3
mov r2,#0
mov r3,a
mov r4,#high (1)
mov r5,#low (1)
lcall lcd_xy ;lcd_xy(7,3)
mov a,var2
add a,var2
mov r3,a
mov a,#0
addc a,#0
mov r2,a
mov a,r3
add a,#low(ch_status)
mov dpl,a
mov a,r2
addc a,#high(ch_status)
mov dph,a
lcall lcd_print1 ;lcd_print(ch_status[var2])
inc var3
ll25:
inc var2
ll19:
mov a,var2
cjne a,#8,ll20
mov a,var3
cjne a,#0,ll28
lcall lcd_print
db "0",0
ll28:
mov var3,#0
lcall lcd_print
db "Receiver status flag: ",0
lcall Buffer
mov lb,r3
mov var2,#0
jmp ll30
ll31:
mov r5,var2 ;num = (byte >> i) & 0x01
mov r0,#0
mov r1,lb
cjne r5,#0,ll32
jmp ll33
ll32:
mov a,r0
clr c
rrc a
mov r0,a
mov a,r1
rrc a
mov r1,a
djnz r5,ll32
ll33:
mov a,r1
anl a,#01h
mov r2,#0
mov r3,a
mov r4,#high (6)
mov r5,#low (6)
lcall lcd_xy ;lcd_xy(7,3)
mov a,var2
add a,var2
mov r3,a
mov a,#0
addc a,#0
mov r2,a
mov a,r3
add a,#low(re_status)
mov dpl,a
mov a,r2
addc a,#high(re_status)
mov dph,a
lcall lcd_print1 ;lcd_print(re_status[var2])
inc var3
ll35:
inc var2
ll30:
mov a,var2
cjne a,#8,ll31
ll41:
lcall EndDisps
ret
;////////////////////////////////////////////////////
Disp_Same:
mov univ,r4
mov f,#1
lcall Init_Text
mov a,univ
cjne a,#0,ww17
lcall lcd_print
db "GPS Receiver Reset!!!",0
jmp ww18
ww17:
cjne a,#1,ww18
lcall lcd_print
db "System Power_On Failure!!!",0
ww18:
lcall EndDisps
ret
;//////////////////////////////////////////////
messages:
dw 0+kk1
dw 0+kk2
dw 0+kk3
dw 0+kk4
dw 0+kk5
dw 0+kk6
dw 0+kk7
dw 0+kk8
dw 0+kk9
dw 0+kk10
dw 0+kk11
dw 0+kk12
dw 0+kk13
dw 0+kk14
dw 0+kk15
dw 0+kk16
kk16:
db "Antenna Undercurrent:",0
kk15:
db "Antenna Overcurrent:",0
kk14:
db "RTC Comm & Time Fail",0
kk13:
db "Temperature Sensor Fail",0
kk12:
db "Ignore",0
kk11:
db "RAM Fail",0
kk10:
db "ROM Fail",0
kk9:
db "1 kHz Presence",0
kk8:
db "Channel 8 Correlation Test Fail!!!",0
kk7:
db "Channel 7 Correlation Test Fail!!!",0
kk6:
db "Channel 6 Correlation Test Fail!!!",0
kk5:
db "Channel 5 Correlation Test Fail!!!",0
kk4:
db "Channel 4 Correlation Test Fail!!!",0
kk3:
db "Channel 3 Correlation Test Fail!!!",0
kk2:
db "Channel 2 Correlation Test Fail!!!",0
kk1:
db "Channel 1 Correlation Test Fail!!!",0
;/////////////////////////////////////////////////
channel:
dw 0+tt1
dw 0+tt2
dw 0+tt3
dw 0+tt4
dw 0+tt5
dw 0+tt6
dw 0+tt7
dw 0+tt8
dw 0+tt9
tt9:
db " - available for position.",0
tt8:
db " - ephemeris acquire.",0
tt7:
db " - satellite time available.",0
tt6:
db " - message sync detect.",0
tt5:
db " - bit sync detect.",0
tt4:
db " - preg acquire.",0
tt3:
db " - AGC set.",0
tt2:
db " - code acquire.",0
tt1:
db " - code search.",0
;///////////////////////////////////////////////////
ch_status:
dw 0+tt10
dw 0+tt11
dw 0+tt12
dw 0+tt13
dw 0+tt14
dw 0+tt15
dw 0+tt16
dw 0+tt17
tt17:
db " - using for position fix.",0
tt16:
db " - satellite momentum alert flag.",0
tt15:
db " - satellite anti-spoof flag set.",0
tt14:
db " - satellite reported unhealthy.",0
tt13:
db " - satellite reported inaccurate(>16m).",0
tt12:
db "",0
tt11:
db "",0
tt10:
db " - parity error.",0
;//////////////////////////////////////////////////
re_status:
dw 0+tt18
dw 0+tt19
dw 0+tt20
dw 0+tt21
dw 0+tt22
dw 0+tt23
dw 0+tt24
dw 0+tt25
tt25:
db " - position propagate mode.",0
tt24:
db " - poor geometry (DOP > 12).",0
tt23:
db " - 3d fix.",0
tt22:
db " - 2d fix.",0
tt21:
db " - acquring satellites.",0
tt20:
db "",0
tt19:
db " - insufficient visible satellites(< 3).",0
tt18:
db " - bad almanac.",0
;/////////////////////////////////////////////////
;Picture for GPS startup (compressed)
Gps_pic_less:
dw 1054, 01fh, 080h, 007h, 080h, 1025, 001h, 0ffh
dw 0f8h, 003h, 0c0h, 1006, 00fh, 0f8h, 1006
dw 00fh, 0f8h, 1009, 07eh, 000h, 007h, 0e3h, 07ch
dw 1006, 07fh, 0ffh, 000h, 003h, 0ffh, 0ffh
dw 1002, 07fh, 0ffh, 1008, 00fh, 0c0h, 000h, 001h
dw 0feh, 01fh, 080h, 1004, 001h, 0ffh, 0ffh
dw 0c0h, 003h, 0ffh, 0ffh, 0e0h, 001h, 0ffh, 0ffh
dw 080h, 1007, 018h, 1003, 003h, 081h, 0c0h
dw 1004, 003h, 0ffh, 0ffh, 0e0h, 003h, 0ffh, 0ffh
dw 0f0h, 003h, 0ffh, 0ffh, 0c0h, 1007, 030h
dw 000h, 00fh, 000h, 001h, 0c1h, 0c0h, 1004, 007h
dw 0f8h, 007h, 0f0h, 003h, 0ffh, 0ffh, 0f8h
dw 003h, 0f0h, 00fh, 0e0h, 1006, 001h, 0e3h, 0e0h
dw 03fh, 0feh, 000h, 078h, 0f0h, 1004, 00fh
dw 0c0h, 001h, 0f8h, 003h, 0c0h, 000h, 0fch, 007h
dw 0c0h, 003h, 0f0h, 1006, 003h, 007h, 0e0h
dw 07fh, 0feh, 000h, 00ch, 038h, 1004, 01fh, 1002
dw 0f8h, 003h, 0c0h, 000h, 07ch, 00fh, 080h
dw 000h, 0f0h, 1006, 006h, 01fh, 0c0h, 0ffh, 0feh
dw 003h, 086h, 01ch, 1004, 01eh, 1002, 07ch
dw 003h, 0c0h, 000h, 03eh, 00fh, 1002, 0f8h, 1006
;///////////////////////////////////////////////////
Final:
jmp Final
end
Appendix G
Included Disc
gpscomp:
This directory contains C++ files to interface the GPS via the serial port to the PC. All information is displayed on the PC.
gpslcd:
This directory contains C++ files to interface the GPS via the serial port to the PC and the LCD via the parallel port to the PC.
asem:
This directory contains the assembly program file and a cross-assembler.