Sunteți pe pagina 1din 62

ELEC2117

GPS Project Report


William Baxter

z3463372

05/06/2014

Contents
1

OVERVIEW ........................................................................................................... 2

DETAILED DESIGN CRITERIA .................................................................................. 2


2.1

Keypad .............................................................................................................. 3

2.2

LCD ................................................................................................................. 3

2.3

GPS .................................................................................................................. 4

2.4

Waypoint System .................................................................................................. 5

2.5

Power Usage ....................................................................................................... 5

SOFTWARE DESIGN ............................................................................................... 7


3.1

Interface............................................................................................................. 8

3.2

Keypad .............................................................................................................. 9

3.3

LCD ................................................................................................................ 10

3.4

GPS ................................................................................................................. 11

3.5

Memory management ........................................................................................... 12

3.5.1

GPS coordinates ........................................................................................... 13

3.5.2

Waypoints .................................................................................................. 13

TESTING AND RESULTS ......................................................................................... 14

DISCUSSION AND ANALYSIS ................................................................................... 14


5.1

Keypad redesign .................................................................................................. 15

5.2

Positional accuracies ............................................................................................. 15

5.3

Power consumption.............................................................................................. 16

5.4

Possible system improvements ................................................................................. 16

CONCLUSION ...................................................................................................... 16

APPENDIX ........................................................................................................... 17

OVERVIEW

The purpose of this report is to detail the necessary steps which were undertaken to produce a fully-functioning
global positioning system and to become familiar with the assembly language program that was used in its design.
In coordination with the provided PIC16F886 microcontroller, this project involved the assimilation of several
different modules and their interfacing through a variety of hardware and software means.
The final design involves implementing a system that is capable of displaying the users current global position
using latitude and longitude in degrees decimal minutes in response to a button press. If the system is unable to
obtain a lock on the satellite, an appropriate message must be displayed. The user must also have the ability to
input up to three waypoints, each of which corresponding to a specific time and location, with the system
signalling the user if they are not present at these specified locations at those particular times.
In retrospect, the project was commenced and accomplished as a series of small problems, with each stemming
from the criterions provided in the Detailed Design Criteria section. Through their eventual clarification, the
objectives of how to produce a successful GPS with the provided parts and the steps needed to be taken were
realised, with the remainder of this report detailing the creative and constructive processes involved.

DETAILED DESIGN CRITERIA

The entire GPS system is designed to be a combination of individual components that will work in tandem with
one another to produce a viable working system for the user. The key physical components comprising the
system were the LCD, keypad and GPS module. As the entire system was designed to be portable, this implied
the use of a mobile power source that would allow the user to properly interface with the system.
As the LCD and the keypad were the only forms of interfacing between the user and the system itself, much
thought was placed into the user interface and the menus that were to be designed. It was apparent that a robust
user interface combined with favourable coding practice could produce a very intuitive system for the user. The
LCD will print messages and characters according to what menu the user is in and in response to any userprovided input. Five LEDs are also used alongside the LCD as a visual indication regarding the users
whereabouts in relation to their inputted waypoints. In conjunction with the keypad, the software used to
implement the final design of the system provides an intuitive and user-friendly experience, with all components
being powered off a Duracell Coppertop (6LR61) 9V battery.
The final design criteria for successfully producing this particular system are listed below:
-

Display current position (latitude and longitude) in response to a button press.


Display 'No GPS lock' if there is no GPS lock.
Allow the user to input 3 waypoints.
The system must signal the user if they are not at the specific locations at the specified times.
Must have a simple and intuitive menu system that the user can quickly grasp.
All data being displayed on the LCD must be contained within a 16 character limit to prevent any added
viewing complexities.
The final design must be entirely portable and capable of enduring sustained use.

2.1 Keypad
The keyboard provided is of a generic hexadecimal format and allows for numeric or alphanumeric information
to be entered. Internally, the keypad consists of touch-activated switches arranged in a matrix fashion of rows and
columns as shown in Figure 2.1.1. As an input device, this requires the first four pins (columns) to be outputs
and the last four pins (rows) to be inputs. The columns of the keypad were pulled up to 5V (active low) using
10k resistors. This was done so as to produce a unique output pattern whenever a key was pressed; with the
row of that particular key being connected to its corresponding column. Such a pattern was able to be detected
by sending a "walking-zero" pattern over the output lines (rows) and then by reading the input lines (columns);
searching for a '0'. The method of determining exactly which key was pressed will be explained under header 3.2
of section 3: Software Design. The circuit diagram in Figure 2 depicts the pin layout and connections that was
used to interface the keypad with the PIC microcontroller.

Figure 2.1.1: Touch activated switches


arranged in a row and column matrix for the
keypad

2.2 LCD
The LCD provided was a PC1601-A LCD display driven by the Samsung KS0066U, with the 64.5 x 13.8mm
viewing module providing either a single line or dual line display with up to sixteen characters at a time. Its presaved driver module includes ASCII character patterns which are able to be accessed using the relevant ASM
commands and supports sixteen custom-generated characters.
Although sufficient for our uses, this provided very limited interfacing possibilities for the user, with much
thought being invested into how this component would interface with the user and any possible restrictions that it
might impose. Rectangular in shape, the entire module itself measures 80.0 x 36.0mm, with a dot size of 0.55 x
0.75mm and dot pitch of 0.63 x 0.83mm. Positioned centrally downwards on the board, wire management was
imperative towards constructing a nice, clean interface, with wires being tightly routed back to the PIC.
This particular LCD module provided backlighting capabilities, and was able to illuminate the entire viewing
module, enhancing its use when in darker environments. The ability to tweak the viewing contrast was also
present, providing the user with a multitude of viewing experiences at the cost of power consumption, as will be
3

discussed in section 5.2: Power Consumption. Testing resulted in the conclusion that without any
backlighting, the display could be rather dim if not outdoors or using a peripheral light source. As such, it was
decided to implement the system with backlighting and with a small tweak also being made to the contrast; both
considerations aiming to improve the viewing experience.
In terms of pin functions and connections, Table 2.2.1 below describes the function for each pin, with the
appropriate connections made to the PIC shown by the circuit diagram in Figure 2.

Pin number

Symbol

Function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Vss
Vdd
Vo
RS
R/W
E
DB0
DB1
DB2
DB3
DB4
DB5
DB6
DB7
A
K

Power supply (-)


Power supply (+)
Contrast adjust
Register select signal
Data read/write
Enable signal
Data bus line
Data bus line
Data bus line
Data bus line
Data bus line
Data bus line
Data bus line
Data bus line
Power supply for LED B/L (+)
Power supply for LED B/L (-)

Table 2.2.1: Pin functions for the PC1601-A


LCD display

2.3 GPS
The Adafruit Ultimate GPS Breakout v3 module provided is built around the MTK3339 chipset and is able to
track up to 22 satellites on 66 channels. Powering off a CR1220 coin cell, the 'Fix' LED blinks at approximately
1Hz while searching for satellites and will blink once every 15 seconds when a fix is found to conserve power. As
the PIC16F886 microcontroller supports EUSART (Enhanced Universal Synchronous Asynchronous Receiver
Transmitter), the GPS module is able to be connected to the appropriate port of the PIC (PORTC) provided that
all relevant bits have been set, as shown in section 3: Software Design.
For the purposes of this project, it is not necessary to transmit to the GPS. For this particular system, we are only
to read from the GPS and to output the relevant data in a cohesive manner for the user to interpret. Upon
performing the necessary software requirements as will be described in the proceeding section, we were able to
connect the TX pin of the GPS module to the RX pin of PORTC,7 on the PIC. The only other ports to be
connected were the VIN (voltage in) and GND (ground) pins, as seen in Figure 2.

2.4 Waypoint System


Provided that the user has added the necessary data for their desired waypoints, it is necessary to implement a
procedure that will automatically verify if the user is present at their desired locations at the specified times.
In order for the system to signal whether the user has arrived at or is absent from a particular waypoint, three
blue LEDs are used in coordination with one white scanning LED and a red no fix LED. If the user is present
at a waypoint during the specified time, the LED for that specific waypoint will be off; if not, then the LED will
turn on.
The scanning LED will flash once every 8 seconds to signify that the current time and users position has been
updated and cross referenced with the newly retrieved GPS coordinates. With every pulse of the white LED, the
users current GPS coordinates are being stored inside the allocated general purpose registers (GPRs) and an
algorithm used to differentiate whether the current time matches that of the specified time for the desired
waypoint. If so, it will continue to resolve whether the user is at that particular waypoint. With each pulse, the
system will scan through all three waypoints and signal the user accordingly as to their positional status with
respect to all locations.
The red no fix LED displays the fix status of the GPS, turning a solid red when a void valid bit has been read,
and turned off when a fix has been established. When the no fix LED burns a solid red, this indicates that the
system is not able to perform any waypoint checking procedures, and must wait for the GPS to obtain a lock
before comparing the users current coordinates to those stored in the waypoint registers.
Figure 2 depicts how the five LEDs are connected within the system, with the three blue LEDS being connected
to ports 0, 1 and 2 of PORTC and the white and red LED connected to ports 5 and 4 of PORTC respectively.

2.5 Power Usage


With the system being designed as a mobile GPS unit that the user can carry all times, it was necessary to
implement a power source that was small and unobtrusive and was able to provide adequate power to the system
for prolonged use.
As most, if not all, components of the system are capable of natively operating at 5V, the L7800 series voltage
regulator was used to step down the voltage provided by the Duracell Coppertop Alkaline 9V source to the
voltage levels required for suitable operation. As shown section 5.2: Power Consumption, implementing the
system in such a manner resulted in the system being capable of providing approximately 4 hours of continuous
use to the user on a single battery.
To complement the portability requirements of the final design, all components were mounted on the EMTEK
E-112A prototyping board, with all components positioned towards the centre row of the prototyping board to
ensure sturdy, reliable connections were made with the soldered electrical contacts underneath the plastic gridtop.

Figure 2: Circuit schematic of the final design

SOFTWARE DESIGN

As this system was heavily dependent on the software that would combine each of its components as a viable,
working product, it was important that the system contain an interface that was as intuitive and user-friendly as
possible. This was accomplished through the use of efficient coding technique so as to reduce the number of
operations necessary for the PIC to perform throughout its operation. System efficiency was paramount towards
obtaining an efficient final design, with 1806 lines of program memory being used by the PIC to implement the
final design of the system.
This was done by ensuring that all memory was
being managed as efficiently as possible through
the use of a variety of memory management
techniques, as will be discussed further in this
section. Such memory management was vital
towards producing an efficiently functioning
system, with program memory, general purpose
registers and electronically erasable memory
(EEPROM) all being considered as viable
methods of satisfying the design criteria towards
producing a functionally efficient system. The
block diagram in Figure 3.2 below depicts the
data and information transfer occurring between
each main component in the final design.

Figure 3.1: Total program memory usage


of the final design

Interrupts were not used in the final design so as to obtain greater control over the system, determining which
functions and routines were to be executed and when. A system of counters and self-implemented flags were
used instead to manipulate the flow of subroutines from one operation to another; with this kind of
implementation proving difficult to use in regards to interrupts, as it would not be possible for the program to
directly access the call stack.

Figure 3.2:
Block diagram depicting
data and information flow
between each of the main
components

The form of implementation seen in Figure 3.2 used very little program memory, and proved far more efficient
in comparison to earlier iterations of the design. For the remainder of this section, the following headers will
describe the processes taking place in the flowchart provided in Figure 7.3 of the Appendix and will detail the
relevant levels of abstraction needed to implement each of the functions necessary in ensuring the systems
reliable operation.

3.1 Interface
The final design for this system contained two primary menus: the main home menu shown on system start-up
and the waypoint menu with which the user would input their desired coordinates. Being comprised of these two
high-level menus, the interface itself seamlessly allows the user to travel back and forth between the two; the two
main menus being linked through the use of on-screen instructions and smaller intermediate menus. This was
done so as to allow the user to intuitively operate the system without needing to enquire as to the specific
functions behind each key.
The home menu displays the ASCII values of the seven keys which each perform different functions, as seen in
Table 3.1.1.

Table 3.1.1: Home screen menu key


functions
In conjunction with the keypad and the characters |A-O-B-C||F-E-D| being displayed like so, the main menu
will prompt the user as to which key to press in order to perform additional functions. Each key pressed in the
home menu refreshed the display and provided the user with a smaller intermediate menu, displaying the relevant
keys with which to perform certain actions. Upon their choosing, the user would be able to press the F key
within each of these sub-menus to return to the main home screen. This is a significant improvement over
previous iterations of the menu, which had no on-screen prompts and a very limited interface; as a first-time user
would have had no knowledge of what functions each of the keys performed.
When pressing either of the F, E or D keys, the user would enter the waypoint menu, and would be
prompted with the display: Add WP1? Y/N->1/2, with the waypoint number corresponding to the relevant
key being pressed. When confirming the addition of a waypoint, the LCD would print the layout of how the
waypoint would be entered, with a blinking cursor signifying the users current on-screen position. The time
field would display the characters: Time: HH: MM:SS, the latitude field displaying LAT: ----,----.- and the
longitude field displaying: LON: -----,----.-. Each of the - characters would be overwritten by the users input
8

as the relevant ASCII character of the key being pressed was written to the LCD screen, and the cursor
automatically being incremented.
Implementing the waypoint menu in such a fashion provided the user with a logical process of entering their
desired waypoint data without the use of any additional prompts. The A, B, C and D keys also allowed the
user to input the global bearings North, South, East and West; allowing the system to function across all
quadrants of the globe. Upon completing the fields, or by pressing the F key mid-operation, the user would be
returned to the main menu screen, with the Saved message being displayed if all required fields were correctly
entered.

3.2 Keypad
The keypad itself is a vital component of the system, as this is one of the only forms of interfacing that exists
between the user and the system. Although very arbitrary in format, it was important to have a robust keypad
function that would interpret the user's input according to what menu they were in.
As shown in Figure 7.4 of the Appendix, the 'store' and 'count' variables are used to perform the matrix
scanning for the keypad. Upon execution of the key scanning function, all port pins of PORTA must be set to
high excluding the first pin, and the carry flag set to high. This particular row pattern is stored inside the store
register, with the count register indicating the number of iterations with which to cycle between the rows. As
each iteration of the scanning loop is executed, the row pattern is re-energised and rotated throughout the
function using the rrf ASM command. Upon determining which row contained the key that had been pressed,
the column in which the key resided had to be found, and as a pair, could locate the keys position within the
matrix. This was done by performing the XOR (exclusive OR) operation. As the column pins were active low,
by performing the XOR operation on the output of the keypad with the data in the store register, any changes
in bit pattern could be determined, resulting in the relevant keys position being found.
As the scanning function for the keypad operates at a much faster rate than our human reaction times, a
debouncing function must be implemented so as to allow the user to comfortably interface with the system. The
release function seen in Figure 7.4 of the Appendix provides a reliable method of determining if the user has
held down a key for an extended period of time, rendering that particular key press as invalid.
Initially, the keypad's scanning system was designed to be a function that the program would initially enter before
looping consistently. When a button was pressed, the program would go to other pre-determined sections of
code, performing any operation that was previously defined for that key. This form of implementation worked
well for a majority of the project, however it was rather taxing on program memory, as it involved implementing
a look-up table for each menu of the interface. The more significant issue occurred with the final implementation
of the waypoint checking function, as this interfered with the counter that was being implemented for the
scanning system; as will be elaborated in section 5.1: Keypad redesign. In light of these issues, the keypad
scanning function was modified so as to be completely modular; being able to scan the matrix once before
returning to its parent function. This was done by having the keypad instead return the ASCII value of the key
that was pressed, with its parent function being able to manipulate the data upon return. If no keys had been
pressed, the output would be cleared and the scanning function would return a NULL result.
This form of implementation proved highly efficient and rendered the use of a look-up table obsolete. This
allowed for the use of peripheral menus without any additional program memory usage, not only improving
response time, but allowing for greater usability and an improved user interface.
9

3.3 LCD
For the system to be operational, the LCD was the centrepiece of the project, with all menus and designs catering
for its successful operation. In order to implement a robust LCD display function, separate sub-functions had to
first be implemented, which would collaborate with one another in order to produce the reliable outputs as seen
in the final design of the system.
In order to initialise the LCD and have it ready for the user, the read and write subroutines had to first be
implemented. This was performed by observing the read and write operation timing charts provided in
Appendix Figures 7.1 and 7.2. The main difference between writing instructions to the LCD and writing
information to the LCD is the status of the Register Select (RS) bit. When the RS bit is high, the byte written to
the LCD will be a printable character that the LCD can display; when low, the LCD will perform a predetermined function which will alter the LCDs internal operation. When writing an instruction from the micro
processing unit to the module, the enable of the LCD must first be off, and the information from the ports on the
PIC transferred to the data ports of the LCD. Clearing the Read/Write (R/W) bit, the enable must then be
pulsed in order to have the data correctly transferred to the LCD. This can be seen in Figure 7.4 with the
'write_op' subroutine responsible for writing all instruction sets to the LCDs data lines. Alternatively, the
write_MSB_LSB subroutine, differing only by the setting of the RS bit, is responsible for writing information to
the LCD which is able to be printed in the form of ASCII characters.
Reading from the LCD is slightly more troublesome, as this first involves storing the information held on the
ports of the PIC which are connected to the LCD. After disabling the RS bit and enabling the R/W bit, we must
set the enable bit of the LCD before transferring the saved data of the PIC ports to a separate register; in this
case, 'read_status'. This read operation is a necessity as the LCD cannot properly operate without it. Using simple
delays in the hope that the busy flag would be reset during the delayed period proved to be highly inefficient, and
resulted in the LCD performing unpredictably.
To ensure a successful write operation, the 'busy_check' subroutine must be used. In conjunction with the read
operation, this routine performs a bit check on the separate register containing the saved port information from
the PIC. By checking the third bit of the register, we are able to determine if the busy flag is 'high', indicating that
an internal operation is being processed. This bit must be checked, as during this time the next instruction cannot
be accepted until the busy flag has been returned to the 'low' state. This is an integral part of the LCD's
operation, as without it, the LCD will refuse to function correctly and will display incorrect characters. After
having composed these read and write subroutines, the initialisation routine was ready to be produced, as shown
below.

10

Table 3.3.1: LCD initialisation routine

It would have been possible to implement the LCD in 8-bit mode, however this would require an entire port of
the PIC to be dedicated to only the data lines of the LCD. This would prove rather costly for the system's
implementation, as we only had 3 peripheral registers to work with (PORTA, PORTB and PORTC), each with
exactly 8 ports. To account for this, it was decided that the system would be implemented in 4-bit mode, with
each write operation being performed two nibbles at a time in order to transfer an entire instruction to the
module. This is shown by the 'write_init' and 'write_char', detailing the switching of the nibbles in the original
instruction; moving the least significant nibble first to the LCD, followed by the most significant, which in two
cycles allows for the LCD to be given the entire instruction set. This involves the use of a temporary register
'write_reg', which stores the original nibble pattern before swapping them and placing each in the 'W' register,
with the busy flag being checked between each nibble operation.
Having completed the necessary subroutines with which to read and write both characters and data to the
module, it was essential to account for the very limited user interface. With this particular module, the Samsung
KS0066U, certain regions of memory could be written to but not displayed on screen. This called for the
manipulation of the DDRAM addresses inside the LCD, which was the driver memory storing the characters
which were to be displayed. This resulted in the screen functioning as two separate halves, with one ranging from
DDRAM addresses 0 to 7, and the other ranging from DDRAM addresses 40 to 47. A counter was implemented
that would decrement once every time a character was written to the LCD, and upon having crossed to the
second half, peripheral counters were used to ensure that the information displayed onscreen did not push past
DDRAM address 47. In conjunction, the 'clearscreen' function in Figure 7.4 was used when the sixteen character
limit was reached, with the DDRAM counter being reset to its initial decimal value of '8'. By doing so, all
characters were able to be displayed perfectly on screen without any syntax errors or breaks in the printed string.

3.4 GPS
The EUSART on-board the PIC16F886 transmits and receives data using the standard non-return-to-zero (NRZ)
format. NRZ implies that consecutively transmitted data bits of the same value stay at the output level of that bit
without returning to a neutral level between each bit transmission; in other words, an NRZ transmission port
idles in the mark state. Each character transmission consists of one 'start' bit followed by 8 or 9 data bits and is
always terminated by one or more 'stop' bits. The 'start' bit is always a space, and the 'stop' bits are always marks,
11

with the most common data format being 8 bits. The EUSART transmits and receives the LSB first, with the
transmitter and receiver being functionally independent, however sharing the same data format and baud rate.
Moving the decimal value of '25' into the SPBRG register sets the baud rate to 9600bps, meaning that the onboard EUSART would be able to transmit one bit at a time at a speed of 9600 bits per second; a method of
communication also referred to as TTL serial communication. For the EUSART receiver to be enabled, the
following three control bits must be set like so:

Table 3.4.1: EUSART controller bit configurations

All other EUSART control bits are assumed to be in their default state.
The EUSART on-board the PIC already has an in-built busy flag, indicating whether a byte has already been
stored in the buffer that is ready to be used. This flag, called the RCIF flag, must be set before the controller is
able to read the data from the RX port. After determining if the RCIF flag has been set, it is necessary to check
for any framing or over-run errors. A framing error indicates that a stop bit was not seen at the expected time,
and is accessed via the frame error (FERR) bit of the RCSTA register. Without either start or stop bit present,
the microprocessor would not be able to determine which byte the current information being read belongs to.
The over-run error occurs when the RX port is not being accessed and the buffer that stores the incoming string
becomes saturated and unable to hold any more data. However, handling these error checks are extremely
simple, and only involves resetting or moving the appropriate bits as seen in Figure 7.4, namely the CREN bits
and the RCREG register.
As the project brief required that the user be able to display their current latitude and longitude, it was necessary
to filter out the required strings from the stream of data provided by the GPS module. It was decided that in
order to store, display and refresh the user's current global coordinates, the '$GPRMC' string had to be obtained
from the output stream of the GPS, as this particular NMEA (National Marine Electronics Association) sentence
provided the time, fix status, latitude, longitude, ground speed, tracking angle and date. In regards to this
system, it was only the time, fix status, latitude and longitude that were of interest to us.

3.5 Memory management


In the final design, it was realised that the sequential use of general purpose registers would be the most efficient
form of practice towards producing a system that would require as little use of program memory as possible. For
this reason, the use of EEPROM for pre-initialised strings when displaying menus, help prompts, and peripheral
messages was considered a non-viable option in regards to the design criteria, as the methods with which to read

12

and write from the stored strings would prove inefficient and nearly as program intensive as simply reading from
the GPRs.

3.5.1 GPS coordinates


The 'coord_read' function seen in Figure 7.4 of the Appendix is the routine that searches for the actual
'$GPRMC' string inside the raw GPS output. After finding this particular prefix, a method of memory storage
called indirect addressing was used. Indirect addressing is a method of register manipulation that allows the
program to store certain bytes of information using memory addresses instead of pre-defined register names. This
allows for vast amounts of information to be stored quickly and efficiently in sequentially ordered memory.
Having found the necessary NMEA prefix within the GPSs output, this method of memory addressing was used
to store the next thirty-seven bytes of data into the allocated GPRs using the 'store_EUSART' function. After
performing the necessary operations provided in the 'time_fix' function, the GMT output from the GPS would be
converted to our local Sydney time zone, and stored back into the appropriate registers.
With the data now ready to display to the user, the 'fix_check' subroutine in Figure 7.4 was implemented to
account for the "No fix" requirement in the brief. When the GPS would still be finding a fix, the status code of
the valid bit would be a 'V', for Void. If it were an 'A', it would imply Active; in other words, the GPS now
had a lock. To account for when the GPS still hadn't obtained a lock, the value of the appropriate GPR was
XOR'd with the ASCII value 'A'. When the Z flag of the STATUS register was set, this would imply that the GPS
had obtained a fix, and the program would continue to write the values stored inside the general purpose
registers to the LCD display; once again using indirect addressing. By incrementing the file select register (FSR)
and traversing through the thirty-seven GPRs used before, the system was able to display the user's current global
coordinates. If the Z flag of the STATUS register was cleared, the words 'No fix...' would appear on-screen for
four seconds before returning the user to the main menu.

3.5.2 Waypoints
The method with which the user would set their desired waypoints worked similarly to the method used to store
the data obtained from the GPS, except that the data was now inputted via the keypad, with the ASCII value of
the key being printed to the LCD screen.
Having to account for three separate locations, the waypoints definitely consumed the most amount of memory,
with seventy-five general purpose registers being set aside; twenty-five of the registers dedicated to each
waypoint. Only twenty-five registers were needed for each waypoint as the periods and commas were both
ignored during the storage of the users inputted data. For optimum coding efficiency, the current GPS
coordinates were stored on the first bank of program memory, with the entire GPRs of the waypoints residing in
the second. Throughout the development of the final design, the 2048 line program memory threshold was never
crossed, and as such, neither of the PAGESELLING or BANKSELLING ASM commands was needed when
storing the users input into the relevant GPRs. This also resulted in not having to use relocatable code, with the
ASM file able to be compiled as an absolute form of code without requiring any sibling header files with which to
function.
Considering the amount of time required to perform the waypoint checking function (which could take up to an
entire second to perform), it was decided not to use the LCD to prompt the user whether they had arrived at a
particular waypoint. Instead, three 20mA blue LEDs would be used to signal the user's presence at a particular
13

waypoint. If the user was present at a waypoint during the specified time, the LED for that waypoint would turn
off. However, when not present, the LED would turn on. Albeit simple, this form of signalling was chosen so as
to improve the functionality of the system while executing the waypoint checking operation. This was done as
once the desired time had been reached, the checking function would perform extensive tests to determine the
position of the GPS compared to the waypoint. As seen in the flowchart of Figure 7.3 in the Appendix, the
number of subprograms to be executed was rather extensive, and the amount of time required was lengthy
compared to other executed routines. This would result in a considerable delay between the LCD interface and
the user. This implied that if the LCD were to display a message for each waypoint, the user would be locked out
of using the system for a full sixty seconds given the worst case scenario that all three waypoints were set to the
same time. The LCD would consistently display whether the user was at these three waypoints and would
interrupt any previous tasks the user was performing. The use of LEDs as a signal for waypoint checking allowed
the user to still interface with the system while it performed the automatic waypoint check once every eight
seconds, improving user functionality and ultimately the user experience. With one LED per waypoint, this
would prove sufficient in satisfying the design criteria.

TESTING AND RESULTS

Having visited the three locations B617, B616A and B421, the data obtained was tabulated and compared to the
survey coordinates provided. The data was obtained by positioning the antennae of the GPS module over the
golden bolts planted along the walkway of UNSW, with six readings taken from each of the locations B617,
B616A and B421. As will be discussed in section 5.2: Positional accuracies, these values were compared to
the coordinates provided by the UNSW School of Surveying, and would allow for the accuracy of the GPS
readings to be determined; with Table 4.1 below displaying the results.

Table 4.1: Results for positional accuracy


testing performed on the UNSW walkway

DISCUSSION AND ANALYSIS

Throughout the development and construction of the final design, many challenges were faced with the number
of goals to satisfy steadily increasing as the project progressed. This primarily came in the form of software, due
to the almost limitless ways of implementing the system, and also in regards to allowing the design meet the
criteria imposed by the results of the analyses. This section will discuss the various problems which were
encountered during the implementation of the final design and the analyses performed in order to produce a fully
functioning system.
14

5.1 Keypad redesign


Initially, all code was dependent upon the key scan function. After declaring and clearing all registers and
initialising the EUSART controller, the main menu would jump to the key scan function and loop indefinitely
until a key was pressed. However, toward the completion of the project and the implementation of the checking
function, this became a significant design flaw as when the checking function's counter had reached zero, the
program would cancel whatever routine it was executing and return the user to the home menu. In essence, this
meant that every 8 seconds, the user was returned to the main menu regardless of how they interacted with the
system. This design flaw was produced by the fact that the keypad scanning system was based on a looped
mechanism that would produce an output only if there was input; the program would never leave the scanning
function until the user had pressed a key. This resulted in the redesigning of the keypad function to be completely
modular, instead returning the value of whatever key was pressed by the user to the program. With these values,
each menu was now able to have different key press functions without repeating the same matrix scanning
technique, proving far more efficient in terms of program memory usage and execution. As the key scan function
was now modular, the waypoint checking counter was now able to function independently of other routines,
acting as a global counter that would compare current GPS coordinates and user inputted waypoint data every
eight seconds during operation.

5.2 Positional accuracies


The checking function that was implemented to compare the waypoint coordinates to those of the GPS included a
rounding function due to the slight inaccuracies of the GPS module when in open air. As seen in Table 5.2.1,
the coordinates obtained by the GPS contained a small amount of error, with Table 4.1 depicting the second
centi-minute fluctuating even when the GPS was laid still over the golden bolts.

Table 5.2.1: Average GPS results for


B617, B616A and B421 with their respective
uncertainties

At times, these fluctuations would induce a roll-over that would be necessary to consider if the user were to
accurately determine if they were at their waypoint. To account for this, a rounding function was implemented
so as to provide the user with some leeway when it came to comparing their current GPS coordinates with those
of the waypoints. It was determined that the best form of rounding would be to check the user's position within
a 36 metre grid-span in both the latitude and longitude direction. This was done by discarding the final two digits
of the latitude and longitude coordinates and by incrementing and decrementing the tens of milli-minutes;
effectively adding +/-1 to the current latitude and longitude readings provided by the GPS. By cross referencing
each set of coordinates with those stored for the waypoint, this would ensure that the users position was accurate
up to 18 metres in either positive or negative direction of latitude and longitude, improving the functionality of
the system and its usability when becoming mobile.

15

5.3 Power consumption


Each of the LEDs used in the system has a current draw of 20mA, with five LEDs in total being used for
indicating waypoint arrival, scanning and GPS fix status. This implies that the waypoint system could draw up to
100mA when all five LEDs are activated simultaneously. However, the probability for all LEDs to be operating
at the same period of time are highly unlikely, as this would require all three waypoints to have the same specified
time and the user to not have arrived at either of the three locations while having a no-fix status; which is
impossible, as the waypoint system would render all waypoint LEDs inactive if a no-fix status was determined. As
such, when idling, the waypoint system would draw only approximately 20mA on average due to the pulsing of
the scanning LED, and a possible 80mA when considering the worst case scenario.
With the backlight on, the entire system excluding the waypoint LEDs measured approximately 54.6 mA. With
the waypoint LEDs on, this fluctuated to a reading of approximately 63.7 mA due to the consistent pulsing of the
scanning LED.
The Duracell Coppertop 9V battery used to power the system has a rated capacity of 550mAh. Using this value in
conjunction with a possible current draw of 143.7mA, this implies that the system is able to last for
approximately 3.83 hours, or approximately 4 hours before the source is depleted.

5.4 Possible system improvements


Throughout operation, it became apparent that whenever the scanning LED was activated, the entire system was
rendered unusable, with the time function hanging on the current second before resuming normal operation
post-pulse. This was because the main function that was linked to the key scanning input entered the sub-routine
where it would compare the waypoint and GPS times obtained from the module. If a match was determined,
then it would perform the necessary calculations to determine whether the user was at the waypoint. This
particular type of implementation could be fixed with more efficient coding practices, or through an alternative
means of comparing the users waypoint data to those obtained from the GPS module.
Additionally, after having left the one minute window after signalling whether the user is at the waypoint or not,
the waypoint information is not erased from the relevant GPRs. This means in twenty-four hours, the waypoint
will be checked again as the information is still stored. This could be fixed by automatically wiping the
information stored in the waypoint GPRs upon every hard-restart of the system, or by implementing a checking
function to determine whether the GPS time has surpassed the one minute window, and if so, then automatically
deleting the specific waypoint data.

CONCLUSION

The project was a success as it was able to meet all relevant criterions provided by the design proposal and
resulted in a greater understanding regarding the functional aspects of microcontrollers. A deeper knowledge of
lower-level assembly language was also obtained through this interfacing of hardware of software and the
fundamentals of machine language and instruction sets.

16

APPENDIX

Figure 7.1: Time characteristics when writing data to the LCD

Figure 7.2: Time characteristics when reading data from the LCD

17

Figure 7.3: Flowchart


detailing construction and
direction flow of software for
the final design
18

19

20

21

22

list
p=16f886
#include <p16f886.inc>

; list directive to define processor


; processor specific variable definitions

__CONFIG
_CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF
& _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG
_CONFIG2, _WRT_OFF & _BOR21V
cblock

0x020
COUNTERL
COUNTERH
INDEX
d1
d2
d3
write_reg
address_count
read_status
valid
EUSART_count
display_reg
count
store
WP_count

Figure 7.4: Assembly file that was used to


implement the final design

endc

w_temp EQU
status_temp
pclath_temp

0x7D
EQU
EQU

string
fix
lat_D
lat_M
lat_O
lon_D
lon_M
lon_O

H'30'
H'3B'
H'3D'
H'42'
H'47'
H'49'
H'4F'
H'54'

EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU

0x7E
0x7F

WP_1_time
WP_1_lat_D
WP_1_lat_M
WP_1_lat_O
WP_1_lon_D
WP_1_lon_M
WP_1_lon_O

EQU
EQU
EQU
EQU
EQU
EQU
EQU

H'A0'
H'A6'
H'AA'
H'AE'
H'AF'
H'B4'
H'B8'

WP_2_time
WP_2_lat_D
WP_2_lat_M
WP_2_lat_O
WP_2_lon_D
WP_2_lon_M
WP_2_lon_O

EQU
EQU
EQU
EQU
EQU
EQU
EQU

H'B9'
H'BF'
H'C3'
H'C7'
H'C8'
H'CD'
H'D1'

WP_3_time
WP_3_lat_D
WP_3_lat_M

EQU
EQU
EQU

H'D2'
H'D8'
H'DC'

23

WP_3_lat_O
WP_3_lon_D
WP_3_lon_M
WP_3_lon_O

EQU
EQU
EQU
EQU

H'E0'
H'E1'
H'E6'
H'EA'

WP_loop EQU
key_output
remove_count
keypad_xor
interf_delay1
interf_delay2
comp_reg
comp_count
comp_WP
comp_GPS
comp_WP_no
check_count
check_count2
temp_FSR
lon_looknice
round_reg
round_reg1
round_reg2
round_reg3

H'57'
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU

H'58'
H'59'
H'5A'
H'5B'
H'5C'
H'5D'
H'5E'
H'5F'
H'60'
H'61'
H'62'
H'63'
H'64'
H'65'
H'66'
H'67'
H'68'
H'69'

;**********************************************************************
ORG
0x000 ; processor reset vector
nop
goto

main

; go to beginning of program

ORG

0x004

; interrupt vector location

movwf
movf
movwf
movf
movwf

w_temp ; save off current W register contents


STATUS,w
; move status register into W register
status_temp
; save off contents of STATUS register
PCLATH,w
; move pclath register into w register
pclath_temp
; save off contents of PCLATH register

; isr code can go here or be located as a call subroutine elsewhere


movf
movwf
movf
movwf
swapf
swapf
retfie

pclath_temp,w
; retrieve copy of PCLATH register
PCLATH ; restore pre-isr PCLATH register contents
status_temp,w
; retrieve copy of STATUS register
STATUS ; restore pre-isr STATUS register contents
w_temp,f
w_temp,w
; restore pre-isr W register contents
; return from interrupt

main
BANKSEL
ANSEL
clrf
ANSEL
clrf
ANSELH
BANKSEL
TRISA
movlw B'00001111'
movwf TRISA
clrf
TRISB
clrf
TRISC

24

clrf
TRISC
BANKSEL
PORTC
clrf
PORTC
clrf
write_reg
clrf
read_status
clrf
address_count
clrf
valid
clrf
EUSART_count
clrf
display_reg
clrf
count
clrf
store
clrf
WP_count
clrf
WP_loop
clrf
key_output
clrf
remove_count
clrf
keypad_xor
clrf
interf_delay1
clrf
interf_delay2
clrf
comp_reg
clrf
comp_count
clrf
comp_WP
clrf
comp_GPS
clrf
comp_WP_no
clrf
check_count
clrf
check_count2
clrf
temp_FSR
clrf
lon_looknice
movlw
movwf
movlw
movwf
movlw
movwf

D'8'
address_count
D'1'
check_count
D'1'
check_count2

;setting up baud rate


BANKSEL
SPBRG
movlw D'25'
movwf SPBRG
;configuring TXSTA
BANKSEL
TXSTA
movlw B'00100100'
movwf TXSTA
;configuring serial port
BANKSEL
RCSTA
bsf
RCSTA,SPEN
bsf
RCSTA,CREN
call
call

LCD_initial
delay_150

goto

GPS

;------------------------------------------------------------------------;
INITIALISE MENU
;------------------------------------------------------------------------GPS

25

call
menu
goto
menu_nav
;------------------------------------------------------------------------;
KEYPAD FUNCTIONS
;------------------------------------------------------------------------check_count2_reset
movlw D'255'
movwf check_count2
check_count_reset
movlw D'255'
movwf check_count
goto
keyscan
keypad_input
decfsz check_count,1
goto
keyscan
decfsz check_count2,1
goto
check_count_reset
bsf
PORTC,4
movf
FSR,0
movwf temp_FSR
call
coord_read_time
call
check_valid
movf
temp_FSR,0
movwf FSR
bcf
PORTC,4
goto
check_count2_reset
keyscan
bsf
STATUS,0
movlw B'01111111'
movwf store
movlw D'04'
movwf count
rowscan movf
movwf
movf
nop
xorwf
movwf
btfss
goto
rrf
decfsz
goto
clrf
return
keypad_release
movf
movwf
movf
nop
xorwf
btfsc
goto
goto

store,0
PORTA
PORTA,0
store,0
keypad_xor
STATUS,2
keypad_release
store,1
count,1
rowscan
key_output

store,0
PORTA
PORTA,0
store,0
STATUS,2
setchar
keypad_release

setchar
movf

count,0

26

addwf
nop
goto
goto
goto
goto

PCL,1

count1

btfsc
call
btfsc
call
btfsc
call
btfsc
call
return

keypad_xor,0
store_1
keypad_xor,1
store_2
keypad_xor,2
store_3
keypad_xor,3
store_F

count2

btfsc
call
btfsc
call
btfsc
call
btfsc
call
return

keypad_xor,0
store_4
keypad_xor,1
store_5
keypad_xor,2
store_6
keypad_xor,3
store_E

count3

btfsc
call
btfsc
call
btfsc
call
btfsc
call
return

keypad_xor,0
store_7
keypad_xor,1
store_8
keypad_xor,2
store_9
keypad_xor,3
store_D

count4

btfsc
call
btfsc
call
btfsc
call
btfsc
call
return

keypad_xor,0
store_A
keypad_xor,1
store_0
keypad_xor,2
store_B
keypad_xor,3
store_C

movlw
movwf
return

'1'
key_output

movlw
movwf
return

'2'
key_output

movlw
movwf
return

'3'
key_output

count1
count2
count3
count4

store_1

store_2

store_3

27

store_4
movlw
movwf
return

'4'
key_output

movlw
movwf
return

'5'
key_output

movlw
movwf
return

'6'
key_output

movlw
movwf
return

'7'
key_output

movlw
movwf
return

'8'
key_output

movlw
movwf
return

'9'
key_output

movlw
movwf
return

'0'
key_output

movlw
movwf
return

'A'
key_output

movlw
movwf
return

'B'
key_output

movlw
movwf
return

'C'
key_output

movlw
movwf
return

'D'
key_output

movlw
movwf
return

'E'
key_output

store_5

store_6

store_7

store_8

store_9

store_0

store_A

store_B

store_C

store_D

store_E

store_F
movlw 'F'
movwf key_output
return
;------------------------------------------------------------------------;
MAIN MENU
;------------------------------------------------------------------------menu_nav
call
keypad_input
movlw

'0'

28

xorwf
btfsc
call
movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
call

key_output,0
STATUS,2
print_time
'B'
key_output,0
STATUS,2
print_latitude
'C'
key_output,0
STATUS,2
print_longitude
'F'
key_output,0
STATUS,2
add_WP1
'E'
key_output,0
STATUS,2
add_WP2
'D'
key_output,0
STATUS,2
add_WP3
'A'
key_output,0
STATUS,2
remove_WP

goto

menu_nav

add_WP1
call
add_WP1_loop
call
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
goto
insert_WP1
movlw
movwf
goto
add_WP2
call
add_WP2_loop
call
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc

double_check_WP1
keypad_input
'2'
key_output,0
STATUS,2
GPS
'1'
key_output,0
STATUS,2
insert_WP1
add_WP1_loop
WP_1_time
FSR
waypoint_add

double_check_WP2
keypad_input
'2'
key_output,0
STATUS,2
GPS
'1'
key_output,0
STATUS,2

29

goto
goto
insert_WP2
movlw
movwf
goto
add_WP3
call
add_WP3_loop
call
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
goto
insert_WP3
movlw
movwf
goto

insert_WP2
add_WP2_loop
WP_2_time
FSR
waypoint_add

double_check_WP3
keypad_input
'2'
key_output,0
STATUS,2
GPS
'1'
key_output,0
STATUS,2
insert_WP3
add_WP3_loop
WP_3_time
FSR
waypoint_add

double_check_WP1
call
clearscreen
call
delay_150
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

'A'
write_char
'd'
write_char
'd'
write_char
''
write_char
'W'
write_char
'P'
write_char
'1'
write_char
'?'
write_char
''
write_char
'Y'
write_char
'/'
write_char
'N'
write_char
'~'
write_char
'1'
write_char
'/'
write_char

30

movlw
call

'2'
write_char

return
double_check_WP2
call
clearscreen
call
delay_150
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

'A'
write_char
'd'
write_char
'd'
write_char
''
write_char
'W'
write_char
'P'
write_char
'2'
write_char
'?'
write_char
''
write_char
'Y'
write_char
'/'
write_char
'N'
write_char
'~'
write_char
'1'
write_char
'/'
write_char
'2'
write_char

return
double_check_WP3
call
clearscreen
call
delay_150
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw

'A'
write_char
'd'
write_char
'd'
write_char
''
write_char
'W'
write_char
'P'

31

call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

write_char
'3'
write_char
'?'
write_char
''
write_char
'Y'
write_char
'/'
write_char
'N'
write_char
'~'
write_char
'1'
write_char
'/'
write_char
'2'
write_char

return
remove_WP
call
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw

clearscreen
delay_150
'E'
write_char
'r'
write_char
'a'
write_char
's'
write_char
'e'
write_char
''
write_char
'W'
write_char
'P'
write_char
''
write_char
'1'
write_char
'|'
write_char
'2'
write_char
'|'
write_char
'3'
write_char
'|'
write_char
'F'

32

call
remove_loop
call

write_char

keypad_input

movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
call
movlw
xorwf
btfsc
goto

'1'
key_output,0
STATUS,2
remove_WP_1
'2'
key_output,0
STATUS,2
remove_WP_2
'3'
key_output,0
STATUS,2
remove_WP_3
'F'
key_output,0
STATUS,2
GPS

goto

remove_loop

remove_WP_1
movlw
movwf
movlw
movwf
call
goto
remove_WP_2
movlw
movwf
movlw
movwf
call
goto
remove_WP_3
movlw
movwf
movlw
movwf
call
goto

'1'
key_output
WP_1_time
FSR
remove_time
remove_message
'2'
key_output
WP_2_time
FSR
remove_time
remove_message
'3'
key_output
WP_3_time
FSR
remove_time
remove_message

remove_time
movlw D'6'
movwf remove_count
remove_loop_time
movlw '.'
movwf INDF
incf
FSR,1
decfsz remove_count,1
goto
remove_loop_time
remove_lat
movlw D'9'
movwf remove_count
remove_loop_lat

33

movlw
movwf
incf
decfsz
goto
remove_lon
movlw
movwf
remove_loop_lon
movlw
movwf
incf
decfsz
goto
return

'.'
INDF
FSR,1
remove_count,1
remove_loop_lat
D'10'
remove_count
'.'
INDF
FSR,1
remove_count,1
remove_loop_lon

remove_message
call
clearscreen
call
delay_150
movlw
call
movlw
call
movlw
call
movf
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

'W'
write_char
'P'
write_char
''
write_char
key_output,W
write_char
''
write_char
'n'
write_char
'o'
write_char
'w'
write_char
''
write_char
'r'
write_char
'e'
write_char
'm'
write_char
'o'
write_char
'v'
write_char
'e'
write_char
'd'
write_char

call
goto

delay_2
GPS

;------------------------------------------------------------------------;
UART FUNCTIONS
;-------------------------------------------------------------------------

34

overrun_error
BANKSEL
RCSTA
bcf
RCSTA,CREN
bsf
RCSTA,CREN
goto
RX
frame_error
BANKSEL
RCSTA
movf
RCREG,W
goto
RX
RX
BANKSEL
PIR1
btfss
PIR1,RCIF
goto
RX
BANKSEL
RCSTA
btfsc
RCSTA,FERR
goto
frame_error
btfsc
RCSTA,OERR
goto
overrun_error
BANKSEL
RCREG
movf
RCREG,W
BANKSEL
PORTA
return
coord_read
call
xorlw
btfss
goto
call
xorlw
btfss
goto
call
xorlw
btfss
goto
call
xorlw
btfss
goto
call
xorlw
btfss
goto
call
xorlw
btfss
goto
call
xorlw
btfss
goto
movlw
movwf
call

RX
'$'
STATUS,2
coord_read
RX
'G'
STATUS,2
coord_read
RX
'P'
STATUS,2
coord_read
RX
'R'
STATUS,2
coord_read
RX
'M'
STATUS,2
coord_read
RX
'C'
STATUS,2
coord_read
RX
','
STATUS,2
coord_read
D'37'
EUSART_count
store_EUSART

35

call
return

time_fix

movlw
movwf
movf
xorlw
btfss
goto
return

fix
FSR
INDF,W
'A'
STATUS,2
no_fix

movlw
movwf
btfsc
goto
btfsc
goto
incf
return

string
FSR
INDF,0
time_case_1
INDF,1
time_case_2
INDF,1

fix_check

time_fix

time_case_1
incf
btfsc
goto
btfsc
goto
decf
incf
return

FSR,1
INDF,2
time_case_1_4
INDF,3
time_case_1_4
FSR,1
INDF,1

time_case_1_4
decf
decf
decf
decf
decf
decf

INDF,1
INDF,1
INDF,1
INDF,1
FSR,1
INDF,1

return
time_case_2
decf
decf
incf
incf
incf
incf
incf
incf
incf

INDF,1
INDF,1
FSR,1
INDF,1
INDF,1
INDF,1
INDF,1
INDF,1
INDF,1

;Take off 4 hours


;Take off 10 hours

;Take off 20 hours

;Add 6 hours

return
print_time
call
call
movlw

clearscreen
delay_150
'T'

36

call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
time_loop_1
movlw
movwf
time_loop_2
movwf
time_loop_3
call
movlw
xorwf
btfsc
goto
decfsz
goto
decfsz
goto
call
movlw
call
movlw
movwf
movlw
movwf
loop_time_hour
call
incf
decfsz
goto
movlw
call
movlw
movwf
loop_time_min
call
incf
decfsz
goto
movlw
call
movlw

write_char
'i'
write_char
'm'
write_char
'e'
write_char
':'
write_char
''
write_char
''
write_char
''
write_char

D'37'
interf_delay1
movlw D'255'
interf_delay2
keypad_input
'F'
key_output,0
STATUS,2
GPS
interf_delay2,1
time_loop_3
interf_delay1,1
time_loop_2
coord_read
B'10101000'
write_init
string
FSR
D'2'
display_reg
movf
INDF,W
write_char
FSR,1
display_reg,1
loop_time_hour
':'
write_char
D'2'
display_reg
movf
INDF,W
write_char
FSR,1
display_reg,1
loop_time_min
':'
write_char
D'2'

37

movwf
loop_time_sec
call
incf
decfsz
goto
goto

display_reg
movf
INDF,W
write_char
FSR,1
display_reg,1
loop_time_sec
time_loop_1

print_latitude
call
call

clearscreen
delay_150

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

'L'
write_char
'A'
write_char
'T'
write_char
':'
write_char
''
write_char

lat_reset
call
call
movlw
movwf
movlw
movwf
loop_lat movf
call
incf
decfsz
goto

coord_read
fix_check
lat_D
FSR
D'11'
display_reg
INDF,W
write_char
FSR,1
display_reg,1
loop_lat

lat_loop_1
movlw
movwf

D'100'
interf_delay1

lat_loop_2
movwf
lat_loop_3
call
movlw
xorwf
btfsc
goto
decfsz
goto
decfsz
goto

movlw D'255'
interf_delay2
keypad_input
'F'
key_output,0
STATUS,2
GPS
interf_delay2,1
lat_loop_3
interf_delay1,1
lat_loop_2

movlw
call
movlw
movwf

B'10000101'
write_init
D'3'
address_count

goto

lat_reset

38

print_longitude
call
call
bsf
movlw
call
movlw
call
movlw
call
movlw
call

clearscreen
delay_150
lon_looknice,0
'L'
write_char
'O'
write_char
'N'
write_char
':'
write_char

lon_reset
call
call
movlw
movwf
movlw
movwf
loop_lon movf
call
incf
decfsz
goto

coord_read
fix_check
lon_D
FSR
D'12'
display_reg
INDF,W
write_char
FSR,1
display_reg,1
loop_lon

lon_loop_1
movlw
movwf

D'100'
interf_delay1

lon_loop_2
movwf
lon_loop_3
call
movlw
xorwf
btfsc
goto
decfsz
goto
decfsz
goto

movlw D'255'
interf_delay2
keypad_input
'F'
key_output,0
STATUS,2
GPS
interf_delay2,1
lon_loop_3
interf_delay1,1
lon_loop_2

movlw
call
movlw
movwf

B'10000100'
write_init
D'4'
address_count

goto

lon_reset

store_EUSART
movlw string
movwf FSR
store_EUSART_loop
call
RX
movwf INDF
incf
FSR,1

39

decfsz
goto
return

EUSART_count,1
store_EUSART_loop

btfsc
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

lon_looknice,0
move
'N'
write_char
'o'
write_char
''
write_char
'f'
write_char
'i'
write_char
'x'
write_char
'.'
write_char
'.'
write_char
'.'
write_char

clrf
call
call

lon_looknice
delay_2
delay_2

goto

GPS

call
decf
return

increment_cursor
address_count,1

no_fix

move

;------------------------------------------------------------------------;
LCD FUNCTIONS
;------------------------------------------------------------------------LCD_initial
call
delay_150
movlw b'00000011'
call
write_op
call
delay_10
movlw b'00000011'
call
write_op
call
delay_10
movlw b'00000011'
call
write_op
call
delay_10
movlw b'00000010'
call
write_init
movlw b'01001000'
call
write_init
movlw b'00001000'
call
write_init
movlw b'00001100'
call
write_init

40

movlw
call
movlw
call
movlw
call

b'00000110'
write_init
b'00000001'
write_init
b'00001100'
write_init

call
call

clearscreen
delay_150

return
clearscreen
movlw
call
movlw
movwf
return

b'00000001'
write_init
D'8'
address_count

menu
call
call

clearscreen
delay_150

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

'|'
write_char
'A'
write_char
'-'
write_char
'O'
write_char
'-'
write_char
'B'
write_char
'-'
write_char
'C'
write_char
'|'
write_char
'|'
write_char
'F'
write_char
'-'
write_char
'E'
write_char
'-'
write_char
'D'
write_char
'|'
write_char

return
write_init

41

movwf
swapf
call
call

write_reg
write_reg,W
write_op
busy_check

movf
call
call
return

write_reg,W
write_op
busy_check

;for writing nibbles of info to LCD data lines


write_op
bcf
PORTC,3 ;enable off
nop
movwf PORTB ;write info to data ports
bcf
PORTB,5 ;RS is 0
bcf
PORTB,4 ;R/W is 0
bsf
PORTC,3 ;enable on
nop
bcf
PORTC,3 ;enable off
return
;for writing nibbles of characters to LCD data lines
write_MSB_LSB
bcf
PORTC,3 ;enable off
nop
movwf PORTB ;write info to data ports
bsf
PORTB,5 ;RS is 1
bcf
PORTB,4 ;R/W is 0
bsf
PORTC,3 ;enable on
nop
bcf
PORTC,3 ;enable off
return
write_char
movwf
swapf
call
call

write_reg
write_reg,W
write_MSB_LSB
busy_check

movf
call
call

write_reg,W
write_MSB_LSB
busy_check

call
return

LCD_check

LCD_check
decfsz
return
call
return
DDRAM_change
movlw
call
call
return

address_count,1
DDRAM_change

B'10101000'
write_init
delay_10

42

read_op
BANKSEL
TRISB
movlw B'00001111'
movwf TRISB
BANKSEL
PORTB
bcf
bsf
nop
bsf
nop
movf
movwf

PORTB,5 ;RS is 0
PORTB,4 ;R/W is 1

bcf
bcf
bcf

PORTC,3 ;enable is off


PORTB,4 ;R/W is 0
PORTB,5 ;RS is 0

PORTC,3 ;enable is on
PORTB,W
read_status

BANKSEL
clrf
TRISB
BANKSEL
return
busy_check
call
btfsc
goto
return

TRISB
PORTC

read_op
read_status,3
busy_check

;------------------------------------------------------------------------;
WAYPOINTS
;------------------------------------------------------------------------waypoint_add
movlw B'00001111'
call
write_init
call
call

clearscreen
delay_150

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

'T'
write_char
'i'
write_char
'm'
write_char
'e'
write_char
':'
write_char
''
write_char
''
write_char
''
write_char

movlw
call
movlw

B'10101000'
write_init
'H'

43

call
movlw
call
call
movlw
call
movlw
call
call
movlw
call
movlw
call

write_char
'H'
write_char
increment_cursor
'M'
write_char
'M'
write_char
increment_cursor
'S'
write_char
'S'
write_char

movlw
call
movlw
call
call
call
movlw
call
movlw
call

B'10101010'
write_init
':'
write_char
increment_cursor
increment_cursor
':'
write_char
B'10101000'
write_init

movlw D'3'
movwf WP_loop
waypoint_time
movlw D'2'
movwf WP_count
waypoint_loop_time
call
WP_set_keypad
decfsz WP_count,1
goto
waypoint_loop_time
call
increment_cursor
decfsz WP_loop,1
goto
waypoint_time
call
call
call
call
call
call

delay_150
delay_150
delay_150
delay_150
clearscreen
delay_150

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

'L'
write_char
'A'
write_char
'T'
write_char
':'
write_char
''
write_char

movlw

D'3'

44

movwf
movlw
call
movlw
call
movlw
call
movlw
call
call
movlw
call
movlw
call
movlw
call
movlw
call
call
movlw
call

address_count
'-'
write_char
'-'
write_char
'-'
write_char
'-'
write_char
increment_cursor
'-'
write_char
'-'
write_char
'-'
write_char
'-'
write_char
increment_cursor
'-'
write_char

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
movwf

B'10101001'
write_init
'.'
write_char
B'10101110'
write_init
','
write_char
B'10000101'
write_init
D'3'
address_count

movlw
movwf
waypoint_lat
movlw
movwf
waypoint_loop_lat
call
decfsz
goto
call
decfsz
goto
call

D'2'
WP_loop
D'4'
WP_count
WP_set_keypad
WP_count,1
waypoint_loop_lat
increment_cursor
WP_loop,1
waypoint_lat
WP_set_keypad

call
call
call
call
call
call

delay_150
delay_150
delay_150
delay_150
clearscreen
delay_150

movlw
call
movlw

'L'
write_char
'O'

45

call
movlw
call
movlw
call

write_char
'N'
write_char
':'
write_char

movlw
movwf
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
call
movlw
call
movlw
call
movlw
call
movlw
call
call
movlw
call

D'4'
address_count
'-'
write_char
'-'
write_char
'-'
write_char
'-'
write_char
'-'
write_char
increment_cursor
'-'
write_char
'-'
write_char
'-'
write_char
'-'
write_char
increment_cursor
'-'
write_char

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
movwf

B'10101001'
write_init
'.'
write_char
B'10101110'
write_init
','
write_char
B'10000100'
write_init
D'4'
address_count

movlw D'5'
movwf WP_count
waypoint_loop_lon_1
call
WP_set_keypad
decfsz WP_count,1
goto
waypoint_loop_lon_1
call
increment_cursor
movlw
movwf

D'4'
WP_count

waypoint_loop_lon_2
call
WP_set_keypad
decfsz WP_count,1
goto
waypoint_loop_lon_2

46

call
call

increment_cursor
WP_set_keypad

goto

saved

call
call
call
call
call
call

delay_150
delay_150
delay_150
delay_150
clearscreen
delay_150

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

''
write_char
''
write_char
''
write_char
''
write_char
''
write_char
'S'
write_char
'a'
write_char
'v'
write_char
'e'
write_char
'd'
write_char
''
write_char
''
write_char
''
write_char
''
write_char
''
write_char
''
write_char

call

delay_2

movlw
call

B'00001100'
write_init

goto

GPS

saved

increment_cursor
movlw B'00010100'
call
write_init
return
WP_set_keypad

47

call
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movlw
xorwf

keypad_input
'0'
key_output,0
STATUS,2
WP_set_keypad2
'1'
key_output,0
STATUS,2
WP_set_keypad2
'2'
key_output,0
STATUS,2
WP_set_keypad2
'3'
key_output,0
STATUS,2
WP_set_keypad2
'4'
key_output,0
STATUS,2
WP_set_keypad2
'5'
key_output,0
STATUS,2
WP_set_keypad2
'6'
key_output,0
STATUS,2
WP_set_keypad2
'7'
key_output,0
STATUS,2
WP_set_keypad2
'8'
key_output,0
STATUS,2
WP_set_keypad2
'9'
key_output,0
STATUS,2
WP_set_keypad2
'A'
key_output,0
STATUS,2
WP_set_keypadN
'B'
key_output,0
STATUS,2
WP_set_keypadS
'C'
key_output,0
STATUS,2
WP_set_keypadE
'D'
key_output,0
STATUS,2
WP_set_keypadW
'F'
key_output,0

48

btfsc
goto

STATUS,2
WP_set_keypadF

goto

WP_set_keypad

WP_set_keypad2
movf
movwf
call
incf
return
WP_set_keypadN
movlw
movwf
call
incf
return
WP_set_keypadS
movlw
movwf
call
incf
return
WP_set_keypadE
movlw
movwf
call
incf
return
WP_set_keypadW
movlw
movwf
call
incf
return
WP_set_keypadF
movlw
call
goto

key_output,0
INDF
write_char
FSR,1

'N'
INDF
write_char
FSR,1

'S'
INDF
write_char
FSR,1

'E'
INDF
write_char
FSR,1

'W'
INDF
write_char
FSR,1

B'00001100'
write_init
GPS

;------------------------------------------------------------------------;
WAYPOINT CHECKING
;------------------------------------------------------------------------coord_read_time
call
RX
xorlw
'$'
btfss
STATUS,2
goto
coord_read_time
call
RX
xorlw
'G'
btfss
STATUS,2
goto
coord_read_time
call
RX
xorlw
'P'
btfss
STATUS,2
goto
coord_read_time
call
RX
xorlw
'R'
btfss
STATUS,2

49

goto
call
xorlw
btfss
goto
call
xorlw
btfss
goto
call
xorlw
btfss
goto
movlw
movwf
call
call
return
compare_general
movf
incf
movwf
movf
movwf
movf
incf
movwf
movf
return
check_valid
movlw
movwf
movf
xorlw
btfss
goto
bcf
check_time
movlw
movwf
movlw
movwf
call
movlw
movwf
movlw
movwf
call
movlw
movwf
movlw
movwf
call
return
compare_time
movlw

coord_read_time
RX
'M'
STATUS,2
coord_read_time
RX
'C'
STATUS,2
coord_read_time
RX
','
STATUS,2
coord_read_time
D'12'
EUSART_count
store_EUSART
time_fix

comp_WP,0
comp_WP,1
FSR
INDF,0
comp_reg
comp_GPS,0
comp_GPS,1
FSR
INDF,0

fix
FSR
INDF,0
'A'
STATUS,2
no_valid
PORTC,5
WP_1_time
comp_WP
'1'
comp_WP_no
compare_time
WP_2_time
comp_WP
'2'
comp_WP_no
compare_time
WP_3_time
comp_WP
'3'
comp_WP_no
compare_time

string

50

movwf comp_GPS
movlw D'4'
movwf comp_count
compare_time_loop
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
no_match
decfsz comp_count,1
goto
compare_time_loop
call
coord_read
incf
comp_WP,1
incf
comp_WP,1
compare_lat_D
movlw lat_D
movwf comp_GPS
movlw D'3'
movwf comp_count
compare_lat_D_loop
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
decfsz comp_count,1
goto
compare_lat_D_loop
movf
movwf
movf
movwf
movlw
movwf
movf
movwf
incf
movf
movwf
lat_checking_00
movlw
xorwf
btfss
goto
movlw
xorwf
btfss
goto
movlw
xorwf
btfsc
goto
lat_up_check_01
movf
movwf
movf
xorwf
btfss

comp_GPS,0
FSR
INDF,0
round_reg3
lat_M
FSR
INDF,0
round_reg2
FSR,1
INDF,0
round_reg1
'0'
round_reg2,0
STATUS,2
lat_checking_99
'0'
round_reg1,0
STATUS,2
compare_lat_D_continue
'0'
round_reg3,0
STATUS,2
compare_lat_D_continue

comp_WP,0
FSR
INDF,0
round_reg3,0
STATUS,2

51

goto
lat_lower_check_99
lat_up_check_follow_on_01
incf
FSR,1
movf
INDF,0
xorlw
'0'
btfss
STATUS,2
goto
not_at_WP
incf
movf
xorlw
btfss
goto
movf
movwf
incf
incf
incf
goto

FSR,1
INDF,0
'1'
STATUS,2
lat_middle_check_00
FSR,0
comp_WP
comp_WP,1
comp_WP,1
comp_WP,1
compare_lat_O

lat_middle_check_00
movf
INDF,0
xorlw
'0'
btfss
STATUS,2
goto
not_at_WP
movf
FSR,0
movwf comp_WP
incf
comp_WP,1
incf
comp_WP,1
incf
comp_WP,1
goto
compare_lat_O

lat_lower_check_99
decf
round_reg3,1
movf
INDF,0
xorwf
round_reg3,0
btfss
STATUS,2
goto
not_at_WP
incf
FSR,1
movf
INDF,0
xorlw
'9'
btfss
STATUS,2
goto
not_at_WP
incf
FSR,1
movf
INDF,0
xorlw
'9'
btfss
STATUS,2
goto
not_at_WP
movf
FSR,0
movwf comp_WP
incf
comp_WP,1
incf
comp_WP,1
incf
comp_WP,1
goto
compare_lat_O

lat_checking_99

52

movlw '9'
xorwf
round_reg2,0
btfss
STATUS,2
goto
compare_lat_D_continue
movlw '9'
xorwf
round_reg1,0
btfss
STATUS,2
goto
compare_lat_D_continue
movlw '9'
xorwf
round_reg3,0
btfsc
STATUS,2
goto
compare_lat_D_continue
lat_up_check_00
movf
comp_WP,0
movwf FSR
movf
INDF,0
incf
round_reg3,1
xorwf
round_reg3,0
btfss
STATUS,2
goto
lat_middle_check_99
lat_up_check_follow_on_00
incf
FSR,1
movf
INDF,0
xorlw
'0'
btfss
STATUS,2
goto
not_at_WP
incf
movf
xorlw
btfss
goto
movf
movwf
incf
incf
incf
goto

FSR,1
INDF,0
'0'
STATUS,2
not_at_WP
FSR,0
comp_WP
comp_WP,1
comp_WP,1
comp_WP,1
compare_lat_O

lat_middle_check_99
movf
INDF,0
decf
round_reg3,1
xorwf
round_reg3,0
btfss
STATUS,2
goto
not_at_WP
incf
movf
xorlw
btfss
goto

FSR,1
INDF,0
'9'
STATUS,2
not_at_WP

incf
movf
xorlw
btfss
goto
movf
movwf

FSR,1
INDF,0
'9'
STATUS,2
lat_lower_check_98
FSR,0
comp_WP

53

incf
incf
incf
goto

comp_WP,1
comp_WP,1
comp_WP,1
compare_lat_O

lat_lower_check_98
movf
INDF,0
xorlw
'8'
btfss
STATUS,2
goto
not_at_WP
movf
FSR,0
movwf comp_WP
incf
comp_WP,1
incf
comp_WP,1
incf
comp_WP,1
goto
compare_lat_O
compare_lat_D_continue
movlw H'40'
movwf comp_GPS
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
compare_lat_M_first
movlw lat_M
movwf comp_GPS
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
compare_lat_M_second
call
compare_general
movwf round_reg
movlw '0'
xorwf
round_reg,0
btfsc
STATUS,2
goto
normal_lat_checking_function
movlw '9'
xorwf
round_reg,0
btfsc
STATUS,2
goto
normal_lat_checking_function
movf
round_reg,0
incf
round_reg,1
movf
round_reg,0
xorwf
comp_reg,0
btfsc
STATUS,2
goto
lat_M_round2
decf
round_reg,1
movf
round_reg,0
xorwf
comp_reg,0
btfsc
STATUS,2
goto
lat_M_round2
decf
round_reg,1
movf
round_reg,0
xorwf
comp_reg,0
btfsc
STATUS,2
goto
lat_M_round2

54

goto

not_at_WP

normal_lat_checking_function
movf
round_reg,0
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
lat_M_round2
incf
comp_WP,1
incf
comp_WP,1
compare_lat_O
movlw lat_O
movwf comp_GPS
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP

compare_lon_D
movlw lon_D
movwf comp_GPS
movlw D'4'
movwf comp_count
compare_lon_D_loop
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
decfsz comp_count,1
goto
compare_lon_D_loop
movf
comp_GPS,0
movwf FSR
movf
INDF,0
movwf round_reg3
movlw lon_M
movwf FSR
movf
INDF,0
movwf round_reg2
incf
FSR,1
movf
INDF,0
movwf round_reg1
lon_checking_00
movlw '0'
xorwf
round_reg2,0
btfss
STATUS,2
goto
lon_checking_99
movlw '0'
xorwf
round_reg1,0
btfss
STATUS,2
goto
compare_lon_D_continue
movlw '0'
xorwf
round_reg3,0
btfsc
STATUS,2
goto
compare_lon_D_continue
lon_up_check_01
movf
comp_WP,0

55

movwf FSR
movf
INDF,0
xorwf
round_reg3,0
btfss
STATUS,2
goto
lon_lower_check_99
lon_up_check_follow_on_01
incf
FSR,1
movf
INDF,0
xorlw
'0'
btfss
STATUS,2
goto
not_at_WP
incf
movf
xorlw
btfss
goto
movf
movwf
incf
incf
incf
goto

FSR,1
INDF,0
'1'
STATUS,2
lon_middle_check_00
FSR,0
comp_WP
comp_WP,1
comp_WP,1
comp_WP,1
compare_lon_O

lon_middle_check_00
movf
INDF,0
xorlw
'0'
btfss
STATUS,2
goto
not_at_WP
movf
FSR,0
movwf comp_WP
incf
comp_WP,1
incf
comp_WP,1
incf
comp_WP,1
goto
compare_lon_O
lon_lower_check_99
decf
round_reg3,1
movf
INDF,0
xorwf
round_reg3,0
btfss
STATUS,2
goto
not_at_WP
incf
FSR,1
movf
INDF,0
xorlw
'9'
btfss
STATUS,2
goto
not_at_WP
incf
FSR,1
movf
INDF,0
xorlw
'9'
btfss
STATUS,2
goto
not_at_WP
movf
FSR,0
movwf comp_WP
incf
comp_WP,1
incf
comp_WP,1
incf
comp_WP,1
goto
compare_lon_O

56

lon_checking_99
movlw '9'
xorwf
round_reg2,0
btfss
STATUS,2
goto
compare_lon_D_continue
movlw '9'
xorwf
round_reg1,0
btfss
STATUS,2
goto
compare_lon_D_continue
movlw '9'
xorwf
round_reg3,0
btfsc
STATUS,2
goto
compare_lon_D_continue
lon_up_check_00
movf
comp_WP,0
movwf FSR
movf
INDF,0
incf
round_reg3,1
xorwf
round_reg3,0
btfss
STATUS,2
goto
lon_middle_check_99
lon_up_check_follow_on_00
incf
FSR,1
movf
INDF,0
xorlw
'0'
btfss
STATUS,2
goto
not_at_WP
incf
movf
xorlw
btfss
goto
movf
movwf
incf
incf
incf
goto

FSR,1
INDF,0
'0'
STATUS,2
not_at_WP
FSR,0
comp_WP
comp_WP,1
comp_WP,1
comp_WP,1
compare_lon_O

lon_middle_check_99
movf
INDF,0
decf
round_reg3,1
xorwf
round_reg3,0
btfss
STATUS,2
goto
not_at_WP
incf
movf
xorlw
btfss
goto

FSR,1
INDF,0
'9'
STATUS,2
not_at_WP

incf
movf
xorlw
btfss
goto

FSR,1
INDF,0
'9'
STATUS,2
lon_lower_check_98

57

movf
movwf
incf
incf
incf
goto

FSR,0
comp_WP
comp_WP,1
comp_WP,1
comp_WP,1
compare_lon_O

lon_lower_check_98
movf
INDF,0
xorlw
'8'
btfss
STATUS,2
goto
not_at_WP
movf
FSR,0
movwf comp_WP
incf
comp_WP,1
incf
comp_WP,1
incf
comp_WP,1
goto
compare_lon_O
compare_lon_D_continue
movlw H'4D'
movwf comp_GPS
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
compare_lon_M_first
movlw
movwf
call
xorwf
btfss
goto

lon_M
comp_GPS
compare_general
comp_reg,0
STATUS,2
not_at_WP

compare_lon_M_second
call
movwf
movlw
xorwf
btfsc
goto
movlw
xorwf
btfsc
goto
movf
incf
movf
xorwf
btfsc
goto
decf
movf
xorwf
btfsc
goto

compare_general
round_reg
'0'
round_reg,0
STATUS,2
normal_lon_checking_function
'9'
round_reg,0
STATUS,2
normal_lon_checking_function
round_reg,0
round_reg,1
round_reg,0
comp_reg,0
STATUS,2
lon_M_round2
round_reg,1
round_reg,0
comp_reg,0
STATUS,2
lon_M_round2

58

decf
movf
xorwf
btfsc
goto
goto

round_reg,1
round_reg,0
comp_reg,0
STATUS,2
lon_M_round2
not_at_WP

normal_lon_checking_function
movf
round_reg,0
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
lon_M_round2
incf
comp_WP,1
incf
comp_WP,1
compare_lon_O
movlw lon_O
movwf comp_GPS
call
compare_general
xorwf
comp_reg,0
btfss
STATUS,2
goto
not_at_WP
at_WP
movlw
xorwf
btfsc
bcf
movlw
xorwf
btfsc
bcf
movlw
xorwf
btfsc
bcf
return
not_at_WP
movlw
xorwf
btfsc
bsf
movlw
xorwf
btfsc
bsf
movlw
xorwf
btfsc
bsf
return
no_match
movlw
xorwf
btfsc
bcf
movlw

'1'
comp_WP_no,0
STATUS,2
PORTC,2
'2'
comp_WP_no,0
STATUS,2
PORTC,1
'3'
comp_WP_no,0
STATUS,2
PORTC,0

'1'
comp_WP_no,0
STATUS,2
PORTC,2
'2'
comp_WP_no,0
STATUS,2
PORTC,1
'3'
comp_WP_no,0
STATUS,2
PORTC,0

'1'
comp_WP_no,0
STATUS,2
PORTC,2
'2'

59

xorwf
btfsc
bcf
movlw
xorwf
btfsc
bcf
return

comp_WP_no,0
STATUS,2
PORTC,1
'3'
comp_WP_no,0
STATUS,2
PORTC,0

bsf
return

PORTC,5

no_valid

;------------------------------------------------------------------------;
DELAYS
;------------------------------------------------------------------------delay_10
movlw 0xCE
movwf d1
movlw 0x08
movwf d2
delay_10_0
decfsz d1, f
goto
$+2
decfsz d2, f
goto
delay_10_0
goto
$+1
nop
return
delay_150
movlw 0x2E
movwf d1
movlw 0x76
movwf d2
delay_150_0
decfsz d1, f
goto
$+2
decfsz d2, f
goto
delay_150_0
goto
$+1
nop
return
delay_2
movlw
movwf
movlw
movwf
movlw
movwf
delay_2_0
decfsz
goto
decfsz
goto
decfsz
goto
return

0x11
d1
0x5D
d2
0x05
d3
d1, f
$+2
d2, f
$+2
d3, f
delay_2_0

60

;------------------------------------------------------------------------;
END
;------------------------------------------------------------------------END

61