Diver Positioning System - My FIT

Transcription

Diver Positioning System - My FIT
Development and Testing of an Acoustic Based
Underwater Positioning System
By Douglas Palmer Bowlus
Bachelor of Science
Electrical Engineering
Ohio University
2005
A thesis submitted to
Florida Institute of Technology
in partial fulfillment of the requirements
for the degree of
Master of Science
In
Ocean Engineering
Melbourne, Florida
May, 2008
The undersigned committee hereby recommends that the attached document be
accepted as fulfilling in part the requirements for the degree of Master of Science in
Ocean Engineering.
Development and Testing of an Acoustic Based Underwater Positioning
System
by
Douglas Palmer Bowlus
George Maul, Ph.D.
Program Chair, Ocean Engineering
Stephen Wood, Ph.D., P.E.
Assistant Professor, Ocean Engineering – Major Advisor
Lee Harris, Ph.D., P.E.
Associate Professor, Ocean Engineering – Committee Member
Hector Gutierrez, Ph.D., P.E.
Associate Professor, Mechanical Engineering – Outside Committee Member
Abstract
Development and Testing of an Acoustic Based Underwater Positioning
System
Author:
Douglas Palmer Bowlus
Advisor:
Stephen Wood, Ph.D., P.E.
The locating of objects on the seafloor is a common problem among
SCUBA divers today. Above the ocean’s surface, today’s GPS technology allows
for reasonably accurate positioning of a boat, but, unless conditions are near
perfect, divers still have difficulty finding small objects underwater. Conditions
such as poor visibility, strong currents and inaccurate coordinates compound the
difficulty of this task.
The work contained in this thesis develops an aid to help divers navigate to
underwater objects i.e., an “underwater GPS” system. Unlike traditional methods
of underwater location which involve rope and local landmarks, this system uses an
un-tethered acoustic transponder operating at frequencies of 35 kHz and 45 kHz to
reference the diver’s position to absolute GPS coordinates. A surface buoy uses
super-short baseline navigation and positioning technology to link the diver and the
GPS satellites.
iii
This paper discusses the design, construction and testing of the “underwater
GPS” prototype known as “BADNeS” (Buoy Assisted Diver Navigation System).
Many current technologies make up the BADNeS and are described. The design of
the BADNeS, including buoy orientation sensors, acoustic processor, and
transponder along with the results of the prototype testing are presented.
iv
Table of Contents
List of Figures ....................................................................................................... viii
List of Tables ............................................................................................................x
List of Abbreviations ............................................................................................. xi
Acknowledgements ................................................................................................ xii
1
Introduction ......................................................................................................1
1.1
Objectives ...................................................................................................3
1.2
Scope of Work............................................................................................3
1.3
Background ................................................................................................4
1.3.1
Long Baseline (LBL) .........................................................................5
1.3.2
Short Baseline (SBL) .........................................................................7
1.3.3
Super Short Base Line (SSBL) ..........................................................8
1.3.4
Ultra Short Baseline (USBL) ...........................................................10
1.4
Commercially Available Products ...........................................................11
1.4.1
SOSI DiverGPS-30 ..........................................................................11
2
1.4.2
RJE DLS-1 .......................................................................................12
1.4.3
XIOS EyeSea (USBL)......................................................................13
The BADNeS Design ......................................................................................13
2.1
BADNeS System Description ..................................................................14
2.2
Prototype Functionality ............................................................................16
2.3
Potential Applications ..............................................................................16
2.4
System Accuracy......................................................................................17
2.4.1
GPS Accuracy ..................................................................................18
2.4.2
Acoustic Positioning System Accuracy ...........................................19
2.5
Electronics ................................................................................................24
2.5.1
Buoy .................................................................................................24
2.5.2
Diver Carried Transponder ..............................................................41
v
2.6
Microcontroller Software .........................................................................43
2.7
Transducers ..............................................................................................48
2.7.1
Environmental Factors Affecting Transducer Design......................48
2.7.2
Transducer Design Parameters .........................................................53
2.7.3
Transducer Design ...........................................................................54
2.7.4
Array Design ....................................................................................58
3
Construction ...................................................................................................61
3.1
Electronics ................................................................................................61
3.2
Transducers ..............................................................................................65
3.3
Buoy .........................................................................................................70
3.4
Diver Unit ................................................................................................74
4
Calibration ......................................................................................................75
4.1
Offsets ......................................................................................................75
4.2
Tilt ............................................................................................................76
4.3
Heading ....................................................................................................76
4.4
Electronic Delay .......................................................................................80
5
Post Processing ...............................................................................................81
6
System Performance ......................................................................................86
6.1
GPS Receiver ...........................................................................................86
6.1.1
Data Collection.................................................................................87
6.1.2
Data Processing ................................................................................89
6.2
Magnetometer ..........................................................................................91
6.2.1
Data Collection.................................................................................92
6.2.2
Data Processing ................................................................................93
6.3
Tilt Sensor ................................................................................................95
6.3.1
Data Collection.................................................................................96
6.3.2
Data Processing ................................................................................96
6.4
Super Short Base Line..............................................................................99
6.5
Overall System Performance..................................................................100
7
Conclusion.....................................................................................................103
vi
References .............................................................................................................105
Appendix A: Circuit Diagrams ...........................................................................108
Appendix B: PCB Layout ....................................................................................112
Appendix C: PIC Assembly Code.......................................................................122
Appendix D: MATLAB Code .............................................................................217
Appendix E: Supporting Test Documents .........................................................227
vii
List of Figures
Figure 1 – Buoy Assisted Diver Navigation System in Action .................................4
Figure 2 - An Example of a Long Base Line System. ...............................................5
Figure 3 - An Example of a Short Base Line System With 4 Receiving Elements. ..7
Figure 4 - An Example of a Super Short Base Line System ......................................8
Figure 5 – An Example of an Ultra Short Base Line System. .................................10
Figure 6 – SOSI DiverGPS-30 (Sound Ocean Systems, 2006) ...............................11
Figure 7 – RJE DLS-1 (RJE, 2002) .........................................................................12
Figure 8 – XIOS EyeSea (Divernet, 2002) ..............................................................13
Figure 9 - BADNeS System Diagram ......................................................................14
Figure 10 - Range Error Estimate ............................................................................20
Figure 11 - Tilt Error Estimate .................................................................................22
Figure 12 - Heading Error Estimate .........................................................................23
Figure 13 – GPS Circuit ...........................................................................................26
Figure 14 – Magnetometer Circuit ...........................................................................27
Figure 15 – Tilt Sensor Circuit ................................................................................28
Figure 16 – Transducer Driving Circuit ...................................................................30
Figure 17 – First Stage Buffer / Amplifier ...............................................................32
Figure 18 – 8th Order Filter Circuit ..........................................................................33
Figure 19 - 35 kHz Filter Response .........................................................................34
Figure 20 – Post Gain Amplifier Circuit ..................................................................35
Figure 21 – Tone Decoder Circuit ...........................................................................36
Figure 22 – Acoustic Processor Circuitry ................................................................37
Figure 23 – Data Logger Circuit ..............................................................................38
Figure 24 – Bluetooth Circuit ..................................................................................39
Figure 25 – RS232 Circuit .......................................................................................40
Figure 26 - 45 kHz Band Pass Filter Response ........................................................42
Figure 27 - Main Buoy Processor Flow Chart .........................................................46
Figure 28 - Acoustic Processor Flow Chart .............................................................47
Figure 29 - Transponder Flow Chart ........................................................................48
Figure 30 - Background Noise Levels (Waite, 2002) ..............................................50
Figure 31 - Noise Due to Rain (Waite, 2002) ..........................................................51
Figure 32 - Basic Transducer Design (NDT Resource Center, 2008) .....................55
Figure 33 - Single Transducer Array .......................................................................58
Figure 34 - Two Transducer Array ..........................................................................59
Figure 35 - Three Transducer Array ........................................................................60
Figure 36 – Transponder Board With Solder Paste .................................................63
Figure 37 – Transponder Board After Component Placement ................................63
viii
Figure 38 – Finished Transponder Board.................................................................64
Figure 39 - Drill Template .......................................................................................66
Figure 40 - Drilling Screw Hole ..............................................................................66
Figure 41 - Hole for Wire.........................................................................................67
Figure 42 - Soldering Wires to Piezo Element.........................................................67
Figure 43 - Screw in Cap .........................................................................................68
Figure 44 - Piezo Element Glued to Washer............................................................69
Figure 45 - Measuring Piezo Height ........................................................................69
Figure 46 - After the Resin Pour ..............................................................................70
Figure 47 – Buoy With Electronics Box ..................................................................72
Figure 48 – The Acoustic Array Mount ...................................................................73
Figure 49 – Final Constructed Buoy ........................................................................73
Figure 50 - Diver Carried Transponder ....................................................................74
Figure 51 – Offsets Required to Reference Transponder Position to Buoy Position
..........................................................................................................................75
Figure 52 – Example calibration data (PNI Corporation, 2004) ..............................77
Figure 53 – Data after offsets are applied (PNI Corporation, 2004) ........................78
Figure 54 - Calibrated Magnetometer Output ..........................................................79
Figure 55 - Wave Propagation Over the Acoustic Array (Frey, 2003) ....................83
Figure 56 - Tripod with Tribrach Set Over Point 6 ..................................................88
Figure 57 - Tripod with Tribrach Used to Position GPS Receiver Over Point 6 .....88
Figure 58 - Magnetometer Testing Setup.................................................................92
Figure 59 - Sample Heading Data ............................................................................93
Figure 60 - Plot of Heading Error ............................................................................94
Figure 61 - Plot of Standard Deviation ....................................................................95
Figure 62 - Tilt Sensor Testing With CodaOctopus F180 .......................................96
Figure 63 - Sample Tilt Data....................................................................................97
Figure 64 - Mean Tilt Error......................................................................................98
Figure 65 - Tilt Standard Deviation .........................................................................98
ix
List of Tables
Table 1 - Approximate Coefficients for Speed of Sound (Waite, 2002) .................20
Table 2 – GPS Receiver Testing Results .................................................................91
Table 3 - Computed Offsets .....................................................................................92
Table 4 - Overall Heading Statistics ........................................................................95
Table 5 - Overall Tilt Sensor Statistics ....................................................................99
Table 6 - Overall System Performance Estimate ...................................................102
x
List of Abbreviations
ADC
AGC
BADNeS
DSP
FAT
FIT
GPS
HDOP
HDTP
IC
I2C
I/O
LBL
LED
MIPS
NGS
PC
PCB
PPS
PPT
PVC
RMS
RS232
RTK
SBL
SCUBA
SD
SMD
SPI
SPS
SPST
SVP
SSBL
USBL
WAAS
WGS84
Analog to Digital Converter
Auto Gain Control
Buoy Assisted Diver Navigation System
Digital Signal Processor
File Allocation Table
Florida Institute of Technology
Global Positioning System
Horizontal Dilution of Precision
Horizontal Time Dependant Positioning
Integrated Circuit
Inter-Integrated Circuit
Input - Output
Long Base Line
Light Emitting Diode
Millions of Instructions Per Second
National Geodetic Survey
Personal Computer
Printed Circuit Board
Pulse Per Second
Parts Per Thousand
Polyvinyl Chloride
Root Mean Square
Recommended Standard 232
Real Time Kinematic
Short Base Line
Self Contained Underwater Breathing Apparatus
Secure Digital
Surface Mount Device
Serial Peripheral Interface
Standard Positioning Service
Single-Pole Single-Throw
Sound Velocity Profile
Super Short Base Line
Ultra Short Base Line
Wide Area Augmentation System
World Geodetic System 84
xi
Acknowledgements
I would like to thank the following people:
My family for always being there for me. I wouldn’t have made it this far without
them.
My friends for their support, encouragement and fun times. Specifically I’d like to
mention: Ashley Naimaster for always putting up with me and keeping me
informed of the latest gossip. Adam Priest for always putting a smile on my face
and teaching me to surf. John O’Connell for teaching that all the people from
Miami aren’t from South Beach. Maila Sepri for engaging in nerd talk with me and
always having a good technical joke to share. Missy Aycock for encouraging me
and immersing me in the NOLA culture so I could get a glimpse at what I might
otherwise never have seen… The TNA girls for their great cooking, endless
excitement and support. Ruth Sharp for her willingness to listen no matter how
boring I was and her endless supply of bad jokes that sometimes make me laugh.
Evan Hughes for helping me to relax every once in a while by watching movies
that should’ve never been made.
My professors for instilling their knowledge in me. Specifically I’d like to
mention: Tim Bambeck for all the help and advice he has given me over the years.
He has gone beyond his duties as a professor to help me and for that I cannot thank
him enough. Dr. Harris for providing me work at Florida Tech and other great
locations along the coast. Dr. Swain for loaning me his first surfboard so I could
take a break every once in a while. Dr. Wood for his excitement about my project
and his help in getting it finished. Dr. Gutierrez for his input as my outside
committee member.
My co-workers at Fugro for helping me gain a better understanding of all aspects of
my project and making me feel welcome at my new home in California. I’d
specifically like to thank those I work with on a daily basis: Annick Tardif, Chris
Ham, Cindi Knight, Cindy Pratt, Eddie Stutts, Gilbert Suarez, Herb Tovar, Jeff
Carothers, Robin Villa and Trisha Mouton.
ASR Ltd. for giving me an experience and friends I’ll never forget.
Lastly, I’d like to thank Seaworld for all the good times I had there.
xii
1
1 Introduction
A problem facing divers today is knowing their precise position underwater.
Most scuba divers carry compasses, however, compasses only approximate
positions when their bearings references a landmark and the diver estimates the
distance to the landmark. If adverse conditions such as strong currents or low
visibility arise the landmark can easily be lost. The traditional methods of
circumventing this use lines that can either be laid out between landmarks or
attached to a weight in order to swim circular search patterns. Although these
methods work, they require the diver to be tethered and only provide a position
relative to local objects. The work contained in this thesis develops an aid to help
divers navigate to underwater objects i.e., an “underwater GPS” system. This
paper discusses the design, construction and testing of the “underwater GPS”
prototype known as “BADNeS” (Buoy Assisted Diver Navigation System).
Several solutions to the problem of underwater positioning have already
been designed and are discussed in detail in section 1.3: Long Base Line (LBL),
Short Base Line (SBL), Super Short Base Line (SSBL) and Ultra Short Base Line
(USBL). Many of these solutions use sound coupled with computer processing to
determine position though the scale of each solution is widely varies and has its
own pros and cons.
2
While these solutions may all work, they are not easily adapted into a small
unit that a diver can carry. For example, Long Base Line requires a network of
equipment spanning vast distances to accurately determine the position an
underwater object. This is not practical for diving given that it requires a large
amount of time deploying equipment for each location. Short Base Line requires
that hydrophones be placed at different points on a boat, which is also not very
conducive to recreational diving. Super Short Base Line (SSBL) and Ultra Short
Base Line (USBL) are the two acoustic positioning techniques available with a
small footprint. These require only a small array of hydrophones, and reference
objects with respect to the position of the array. These features make SSBL and
USBL very suitable for a recreational diver’s positioning system. The small array
size allows for easy deployment while the reference method makes transformation
to an absolute positioning system such as the Global Positioning System (GPS)
straightforward.
The technology required for an underwater positioning system already
exists, however, the cost of off the shelf system components is prohibitively high
for personal use. For example, LinkQuest Inc. sells their lowest grade USBL
navigation system starting at $15,000 USD (TrackLink Models, 2005). This price
does not include the GPS, motion sensors and laptop required for a fully
functioning positioning system. In addition to the high cost, the system portability
is less than ideal as each component is housed separately and must be reassembled
3
in a known orientation each time it is to be used. By building all the required
components into a single unit, the portability and cost of an underwater positioning
could become feasible for personal use.
1.1 Objectives
The objective of this project was to develop a portable, low-cost prototype
system capable of providing a diver’s absolute position to a fair degree of accuracy.
The prototype system is known as the “BADNES” (Buoy Assissted Diver
Navigation System). The portability of the BADNES was to be such that it can be
carried by one person and fit on a standard dive boat. The total cost of system
components was to be $1,500 or less for the proto-type unit making the cost of a
mass-produced unit substantially less. The system was desired to have a working
range of 100m (diver to buoy) and an overall horizontal positioning accuracy better
than 10 meters Root Mean Square (RMS).
1.2 Scope of Work
The scope of the project included designing, building, and testing the
conceived proto-type underwater positioning system as depicted in Figure 1. A
board level design was devised based on GPS and acoustic positioning technology.
The proto-type unit was then constructed. Finally, the system functionality was
determined empirically through testing of the proto-type unit.
4
Figure 1 – Buoy Assisted Diver Navigation System in Action
1.3 Background
As mentioned earlier there are currently four popular techniques utilized to
position objects underwater via acoustics: Long Base Line, Short Base Line, Ultra
Short Base Line and Super Short Base Line. These technologies are similar in that
they use the travel time of sound in water, but differ in their spatial requirements
and accuracies.
5
1.3.1 Long Baseline (LBL)
Figure 2 - An Example of a Long Base Line System.
In a long baseline system as seen in Figure 2, three (3) or more beacons are
placed in known locations and used to compute the diver’s position. The beacons
can be mounted in fixed locations or placed on floating buoys which encode their
GPS coordinates in the beacon’s signal. The time it takes sound to travel from the
beacons to the diver is measured. Using the travel time, the range of the diver from
each beacon is computed by assuming a fixed speed of sound in water. By drawing
a circle centered at each beacon with a radius equal to the range to the diver, the
diver’s position is given by the intersection of the three circles. This is essentially
the same principle that GPS (Global Positioning System) uses.
6
The system is termed “long” baseline because the distance between the
beacons for this technique are large and encompass the entire region where
positioning is to be done. Long baselines have more accuracy than other
techniques due to the larger distances and hence longer signal travel times. A
typical accuracy for a long baseline system after calibration would be one (1) meter
(Lurton, 2002). This accuracy can be improved in more advanced systems which
utilize methods such as coded wide band signals (Austin, 1994).
Major disadvantages of the long baseline technique are time and money.
Larger, more expensive transmitters are required to cover the large distances
necessary for accurate positioning. In addition, each transmitter must be set in
location and their coordinates determined before a target position can be found.
For these reasons long baseline is economical for jobs of short duration or noncommercial use.
7
1.3.2 Short Baseline (SBL)
Figure 3 - An Example of a Short Base Line System With 4 Receiving Elements.
Short baseline systems use multiple receiving elements to determine the
distance and bearing of a single transmitter. The bearing is computed by
comparing the difference in arrival time of the transmitter’s signal between
receiving elements. For this to work, the orientation of the receiving elements must
be known. The range is then determined by applying an estimate of the speed of
sound in water to the roundtrip travel time of the signal.
8
Unlike a LBL system, the reference frame is not necessarily fixed. In the
system illustrated in Figure 3, the receiving elements are mounted at different
positions on the bottom of a ship. After a transmitter’s signal is received, the SBL
system will determine a distance and a bearing to the transmitter. Since the SBL
system is attached to the ship, any movement of the ship must be taken into account
to compute the exact position of the transmitter.
A major disadvantage of a SBL system is its setup. The receiving elements
must be mounted and surveyed on each vessel so their orientation relative to each
other is known. The extra time spent mobilizing and demobilizing the SBL system
may not be worth it for a casual diver.
1.3.3 Super Short Base Line (SSBL)
Figure 4 - An Example of a Super Short Base Line System
9
Super short base line (see Figure 4) is the same as short base line except that
the receiving elements are mounted closer together. The difference in arrival time
between the elements is still used to compute the bearing as in SBL, however, these
arrival time differences are much smaller.
The advantages of a SSBL system over a SBL system include easier setup
and smaller space requirement. Instead of mounting and surveying multiple
receiving elements, the elements can be fixed to a small frame. Fixing all the
elements to a frame makes it easy to change vessels since only one point on the
frame needs to be known in reference to the vessel along with the heading of the
frame.
Although SSBL has several advantages, the accuracy is slightly
compromised. Due to the fact that the receiving elements are closer together than
in SBL systems, the resolution of the time of arrival measurements becomes very
important and has a large impact on system accuracy.
10
1.3.4 Ultra Short Baseline (USBL)
Figure 5 – An Example of an Ultra Short Base Line System.
Similar to a SBL system, an ultra short baseline system (shown in Figure 5)
has multiple receiving elements. The difference is that the elements in an USBL
system are contained in one housing with very close spacing. The spacing of each
element is within a wavelength of the others. This allows the phase differences of
the incoming signals between the different receiving elements to be used in order to
find the bearing (as opposed to the arrival time). The range is found the same as
with SBL.
As with SSBL, the main disadvantage of USBL is that of accuracy. A
typical USBL system has positioning accuracies of approximately 10 meters
11
(Lurton, 2002). This accuracy can be improved through the use of advanced
techniques which utilize coded, wide band signals instead of conventional tone
bursts (Austin, 1994).
1.4 Commercially Available Products
A large number of commercially available underwater navigation units were
researched and reviewed. Many similar products to those listed exist but were not
listed to avoid redundancy. Also note that LBL commercial products were omitted
due to their high cost and long mobilization times.
1.4.1 SOSI DiverGPS-30
Figure 6 – SOSI DiverGPS-30 (Sound Ocean Systems, 2006)
The SOSI DiverGPS-30 (shown in Figure 6) is essentially a waterproofed
GPS unit whose antenna is attached to a buoy with a cable.
12
Manufacturer: Sound Ocean Systems, Inc.
http://www.soundocean.com/
Price:
Estimated < $1000 USD
Pros:
-Simple design
-Full featured mapping
-Portability
Cons:
-Tethered antenna
-Positioning is based on antenna
location not diver location
1.4.2 RJE DLS-1
Figure 7 – RJE DLS-1 (RJE, 2002)
The RJE DLS-1 (shown in Figure 7) is used to find an underwater
transmitter. Range and bearing are found by listening for a change in tone while
pointing the device and turning in a circle. While absolute bearing could be
obtained by a diver using a compass, this unit doesn’t lend itself to an automated
diver location system.
Manufacturer: RJE International
http://www.rjeint.com/
Price:
Estimated $5000 USD
Pros:
-Portability
Cons:
-No direct range and bearing information
-No absolute positioning information
13
1.4.3 XIOS EyeSea (USBL)
Figure 8 – XIOS EyeSea (Divernet, 2002)
After attaching a transmitter to an object underwater, the wrist worn
receiver (shown in Figure 8) gives the diver distance and bearing information to the
transmitter.
Manufacturer: XIOS
Price:
$700 USD
Pros:
-Portability
-Provides range and bearing information
Cons:
-No longer available
-No GPS integration
2 The BADNeS Design
The design of the “BADNeS” (Buoy Assisted Diver Navigation System)
prototype incorporated the good qualities of the systems described above. The
functionality, accuracy, hardware and software considerations pertaining to the
design of the BADNeS are described in this section.
14
2.1 BADNeS System Description
Figure 9 - BADNeS System Diagram
By combining the technologies used in the above mentioned commercially
available products, a better diver positioning system was designed. More
specifically, a range and bearing system similar to the XIOS EyeSea unit was
combined with the absolute positioning power of a floating GPS system resembling
the SOSI DiverGPS-30.
The BADNeS positioning system acts as an underwater GPS and consists of
two parts, a buoy and a waterproof transponder (see Figure 9). The buoy holds a
standard GPS unit, orientation sensors (tilt and heading), an acoustic array and a
15
processing unit. The waterproof transponder responds to signals sent from the
surface unit and is carried with the diver or object to be located.
The BADNeS operates in the following basic manner. First, the absolute
position of the buoy is determined via the GPS unit. The acoustic array is then
used to find the transponder’s distance and bearing from the buoy. This is
accomplished by transmitting a signal from the buoy to the transponder which then
responds with a similar signal. Using the roundtrip travel time and an estimate of
the speed of sound in water, the range is determined. The acoustic array also uses
the signal from the transponder to determine the azimuth and elevation bearings of
the transponder relative to the buoy with the super-short baseline technique. The
range and bearing estimate of transponder position is then referenced to the GPS
position using the orientation sensors. The heading sensor is used to reference the
bearing of the transponder to north. The tilt sensors are used to remove any effects
of the buoy’s tilt on the transponder’s position. This process is repeated to
constantly update the transponder’s position.
More functionality can be added to the BADNeS prototype in the future by
incorporating a few extra components. The incorporation of an acoustic modem
into the buoy and transponder enables many possibilities. By adding a depth sensor
to the transponder, the acoustic modems will enable the transponder to send a depth
measurement to the surface unit. The depth measurement can be used to improve
the accuracy of the acoustic positioning calculations. The addition of the modem
16
would also allow the surface unit to send the latest position estimate to the diver
unit for display on a screen if real-time processing were done on the buoy.
2.2 Prototype Functionality
The purpose of the prototype unit was to determine the feasibility of a diver
positioning system as described above and if possible determine the accuracy and
precision of the various components. The prototype design contains all the sensing
capabilities of the system described above: GPS, heading and tilt orientation
sensors, and a super-short baseline acoustic positioning system. The prototype logs
data from the sensors and requires post-processing performed on a PC to determine
the diver position. Real-time processing wasn’t implemented on the prototype to
allow for a quicker design time and more flexibility in the data processing.
2.3 Potential Applications
There are many immediate applications for which the BADNeS could be
used. The ability for a diver to know his absolute position underwater allows for
uses such as:
•
Marking the position of an underwater instrument / artifact / hazard (very
useful in underwater monitoring applications such as for artificial reefs)
•
Finding an underwater instrument / artifact / hazard
17
•
Following a course underwater (this would be very useful in search and
rescue operations)
•
Finding your way to an exit in ice covered areas
•
Avoiding potential hazards
•
Underwater archeology
If BADNeS units were then networked together with real time data transfer,
diver and object positions could be shared instantly. This would provide for even
more applications such as:
•
Locating a lost dive buddy
•
Locating a surface vessel
•
Performing large coordinated searches
•
Alerting others of potential hazards
•
Sharing sightings of artifacts and exotic sea creatures
•
Coordinating underwater efforts such as coral transplantation
2.4 System Accuracy
The performance of the GPS and acoustic positioning system determine the
accuracy of the BADNeS. The accuracy of GPS and the components comprising
the acoustic positioning system are detailed in this section.
18
2.4.1 GPS Accuracy
The positioning accuracy of raw GPS measurements is approximately 10-20
meters (Lekkerkerk, 2007, Vol. 1); this accuracy can be increased by using
Differential GPS (DGPS). Standard DGPS works by setting up a GPS receiver at a
known location to act as a reference station. The reference station measures pseudo
ranges to the satellites while at the same time calculating theoretical pseudo ranges
using its known location. By comparing the theoretical ranges to the measured
ranges the reference station is able to compute a number of corrections. In a DGPS
system, these corrections are transmitted to other nearby GPS receivers allowing
them to calculate their position to within 2 meters (Lekkerkerk, 2007, Vol. 1).
More complicated DGPS systems exist, namely Real Time Kinematic (RTK),
which can provide centimeter level accuracy (Lekkerkerk, 2007, Vol. 1), however,
these systems are prohibitively expensive for the BADNeS.
The Wide Area Augmentation System (WAAS) is a type of DGPS system
comprised of a number of ground based reference stations and a number of
geostationary satellites. In this particular system, the corrections are sent out using
the geostationary satellites allowing corrections to be received by any GPS
receivers within view of one of the satellites. The accuracy of a standard off the
shelf GPS unit is 5m with WAAS enabled (406 GPS Receiver Engine Board,
2006).
19
It is not feasible for a recreational diver to own and setup a base station,
however, many DGPS reference networks, like WAAS, exist that can be used.
Depending on the company running the reference network, special equipment may
be needed, a service fee may apply and the service area may be limited. The
prototype unit has the capability to accept DGPS corrections, though none other
than WAAS were used as it required no additional hardware and is freely available
in the United States of America.
2.4.2 Acoustic Positioning System Accuracy
The accuracy of the acoustic positioning systems is affected by many error
sources. Error sources include: sound velocity, tilt angle, heading, sampling and
false detections. The sources of these errors as well as their consequences are
described below in Sections 2.3.2.1 - 2.3.2.5.
2.4.2.1
Sound Velocity Error
Sound velocity in water is determined by temperature, salinity and depth.
The relative effect of each factor can be seen in Table 1. Given that these factors
vary from one place to another in the ocean, the speed of sound also varies. It is
impossible to know the speed of sound at every point in the ocean so an assumption
is made. In practice the speed of sound is typically assumed to be constant in all
locations or varying only with depth. The latter case makes use of a sound velocity
profile (SVP), a plot of sound speed versus depth.
20
Table 1 - Approximate Coefficients for Speed of Sound (Waite, 2002)
Temperature +3.4 m/s per °C
Salinity
+1.2 m/s per ppt
Depth
+1.7 m/s per 100m
The assumption about sound velocity leads directly to errors in the acoustic
positioning system. Range estimate error is error caused by using the assumed
sound velocity to turn the round distance travel time of sound, from the buoy to the
transponder and back, into a distance. The amount of this error is:
Range Estimate Error =
TRT
× (c r − c a )
2
[1]
Where:
Range Estimate Error is given in meters
TRT = Round trip travel time in seconds
cr
ca
= Real average sound velocity in meters per second
= Assumed average sound velocity in meters per second
Figure 10 - Range Error Estimate
21
As can be seen from Figure 10, range error at 100 meters becomes significant if a
proper sound velocity is not assumed. Refraction error is the other error source due
to an assumed sound velocity though its affects can be reduced if an SVP is
available. Refraction is the bending of sound waves due to changes in the speed of
sound as the waves propagate. If speed of sound is relatively constant in a location
then refraction will not be a problem, however, if a thermocline or halocline is
present refraction can become a significant error source. A SVP can be used to
calculated and remove the effects of refraction from the calculated position
estimate.
2.4.2.2
Tilt Angle Error
Tilt error is the difference between the actual tilt of the SSBL array and the
measurement returned by the tilt sensor. Since any position determined by the
acoustic positioning system is in reference to the acoustic array, the tilt
measurement must be used in order to compute the position in an absolute
coordinate system. Tilt error is introduced by both roll and pitch measurements.
The effect tilt error has on the position estimate increases with range so that at large
ranges it becomes a major source of error (see Figure 11).
22
Figure 11 - Tilt Error Estimate
2.4.2.3
Heading Error
Heading error is the difference between the SSBL array’s actual heading
and that derived from the magnetometer readings. The heading, like tilt, is used to
reference the position of the transponder determined by the SSBL to an absolute
coordinate system such as WGS84, the geodetic datum used by GPS. The effect of
heading error on the position estimate is dependant on the transponder’s range from
the buoy and the elevation bearing as shown in Figure 12.
23
Figure 12 - Heading Error Estimate
2.4.2.4
Sampling Error
Sampling error affects both the range and bearing estimates. This is
because the range and bearing estimates are determined by detecting time
differences between several transducers. The processor samples the signal received
from the transducer a finite number of times per second. The gap in time between
the transducer receiving a signal and the processor sampling this signal is sampling
error. The higher the sampling rate, the lower the sampling error will be. The
sampling rate must be chosen such that the effect it has on the range and bearings is
within the desired tolerance.
24
2.4.2.5
False Detection
Signals from sources other than the transponder can be falsely detected as
the response pulse from the transducer. This occurs when a sound source of the
right frequency is loud enough to be detected and arrives in the interval between the
transmission of the interrogation pulse and the reception of the response pulse.
Unless there is a constant source of noise at the reception frequency, false detection
error is unlikely. If false detection does occur, it is likely the position reported will
be far enough from other measurements to warrant suspicion.
2.5 Electronics
This section describes how the electronics designed for this project came to
be. This includes information on component selection and circuit design for the
buoy and diver carried transponder.
2.5.1 Buoy
The buoy electronics were designed to accomplish five tasks: determine the
position and orientation of the buoy, determine the position of the diver relative to
the buoy, save any data collected and provide an interface for the user.
25
2.5.1.1
Determining Position of the Buoy
The position of the buoy was determined utilizing GPS. A variety of GPS
modules were available to choose from; two of them were incorporated in the
design of the buoy electronics.
Originally the EM-406 by the GlobalSat Technology Corporation was to be
used and was tested on a prototype board. The EM-406 was selected from
Sparkfun Electronics’ available devices for two reasons. At the time it had the
SiRF III chipset, the newest GPS chipset of the available modules (406 GPS
Receiver Engine Board, 2006). It was also the only module with this chipset that
came with a built-in antenna. This rid of the need to match an antenna to the GPS
module and therefore simplified the design.
The second GPS module which can be connected to the main circuit board
is the EB-85A by Etek Navigation, Inc. It was introduced after the EM-406 was
prototyped but before the main circuit board design was finished. While the EM406 specifications list 10 meter 2D RMS error (no WAAS), the EB-85A datasheet
claims 3.3 meter CEP error (un-aided). 2D RMS error is approximately 1.2 times
the CEP error (Misra, 2004) which means the EB-85A has approximately 4 meter
2D RMS error. The EB-85A also features a Pulse Per Second (PPS) output which
allows for precise timekeeping and an update rate of up to 5 Hz. The EM-406 has
no PPS output on its connector and only updates at a maximum rate of 1 Hz. The
26
circuitry for both GPS units was included on the final circuit board but the EB-85A
was used because of the PPS output and lower 2D RMS error.
The circuitry required for the GPS modules (shown in Figure 13) is
relatively basic. The 5 Volt power going to each GPS module is controlled via an
Analog Devices ADG801 digitally controlled SPST switch. This provides the
ability to save power by turning off the GPS module when not in use. The GPS
modules communicate via RS-232 which requires a two-wire interface to the host
microcontroller. The 1PPS output of the EB-85A is connected to an interrupt line
on the host microcontroller and the battery backup line is connected via a jumper to
a 3V lithium coin cell battery.
Figure 13 – GPS Circuit
27
2.5.1.2
Determining the Orientation of the Buoy
The orientation of the buoy consists of its heading, pitch, and roll. The
heading can be determined by measuring the strength of the Earth’s magnetic field
while the pitch and roll can be measured using the Earth’s gravitational field.
A 3-axis magnetometer (MicroMag3) measures the strength of earth’s
magnetic field to determine the buoy’s heading. This sensor provides a high
resolution magnetic field measurement in three axes. The MicroMag3 interfaces
with a microcontroller via an SPI interface and only requires one external
decoupling capacitor (see Figure 14). This device is capable of measuring ± 1100
μT with a resolution of 0.015 μT (PNI Corporation, 2006). This range is sufficient
since the Earth’s magnetic field strength ranges from approximately 20 μT to 65 μT
(National GeoSpatial-Intelligence Agency, 2005).
Figure 14 – Magnetometer Circuit
28
An Analog Devices ADIS16201 dual-axis inclinometer measures the
buoy’s tilt. This sensor uses Earth’s gravitational pull to determine the angle of the
sensor in two dimensions with an accuracy of ± 0.25 degrees for small tilt angles
(Analog Devices, 2006). The ADIS16201 outputs tilt and acceleration data via SPI
when instructed by the host processor. An onboard filter can be adjusted to
decrease the effect of buoy accelerations on the tilt measurement. The sensor can’t
differentiate between static acceleration due to gravity and dynamic acceleration
due to other forces, therefore, a low pass filter is used to minimize this effect. The
ADIS16201 incorporates its own decoupling capacitors so no external components
were required (as shown in Figure 15).
Figure 15 – Tilt Sensor Circuit
2.5.1.3
Determining the Diver’s Relative Position
In order to ascertain the diver’s position relative to the buoy, the super short
baseline technique is used. This technique requires that an interrogation signal is
29
sent to the transponder and the time of arrival of the response pulse is recorded for
each transducer in the receiving array.
The transducer driver sends the interrogation pulse using an Allegro A3950
full bridge motor driver. The A3950 provides a simple method of providing a
maximum of 2.8 amps at up to 36 volts to the transducer as well as ability to
reverse current direction quickly. By reversing current direction, as opposed to
turning the current to the transducer on and off, the effective voltage delivered to
the transducer is doubled. The transducer has high input impedance, therefore,
every bit of voltage helps to deliver a suitable amount of acoustic energy through
the water.
A basic 3.3 volt digital interface is required to control the A3950 full bridge
motor driver. An enable line turns the current to the transducer on when driven
high. A phase line controls the current direction. The interrogation transmit pulse
is generated by toggling the phase line at 45kHz, the interrogation pulse frequency,
while setting the enable line high for the desired pulse length.
The typical application circuit from the A3950 datasheet was used as it
detailed all the required external components. These components provide for
digital line pull-ups, voltage regulation and charge pump capacitance as seen in
Figure 16.
30
Figure 16 – Transducer Driving Circuit
A series of circuits is required to measure the time of arrival of the response
pulse from the transducer array. Since the output of a transducer is high impedance
and low voltage, the first circuit needed is an amplifying buffer circuit. Next a
filter is used to reduce noise and pass only the response pulse frequency. After the
filter, another amplifier with programmable gain is used to boost the voltage to a
suitable level for the next circuit, the tone decoder. The tone decoder circuit detects
a single frequency and sets a digital output alerting the microcontroller if a tone is
detected. The microcontroller then captures the time at which the response pulse is
received.
31
The amplifying buffer circuit incorporates an ultra low-noise Analog
Devices AD745 op-amp as well as a Maxim 5436 digital potentiometer for
programmable gain. The recommended hydrophone circuit given in the AD745
datasheet was used. This circuit provides balanced inputs to the op-amp, an
extremely high input impedance and low output impedance. The Maxim 5436
digital potentiometer is used to vary the feedback current from the output of the opamp to the input. This effectively controls the gain of the first stage amplifier. The
5436 digital potentiometer has a range of approximately 2-52kΏ. The gain for the
first stage amplifier is given by Equation 2.
Gain = Feedback Resistance / R63
[2]
With resistor R63 (shown in Figure 17) set to 100Ώ, this gives a range of
amplification of approximately 20-520 in steps of 40. The step size is due to the
128 finite values the digital potentiometer can take on. This value is set by the
microcontroller via an SPI interface.
32
Figure 17 – First Stage Buffer / Amplifier
A Maxim MAX274 active filter IC is used to implement an 8th order band
pass filter. This IC was chosen because of its ability to implement high order filters
with different center frequencies and bandwidths. Using a software program,
released by Maxim, it’s just a matter of selecting the filter response desired and the
software calculates the 16 external resistors required (see Figure 18). Since this
same circuit was to be used in the diver transponder which uses a different
frequency, this was a major plus. Size was another reason this IC was chosen. It
33
comes in a small surface mount package and even with all the external resistors, it
doesn’t take up much board space. By design the filter has a bandwidth of
approximately 1 kHz and a center frequency of 35 kHz as shown in Figure 19.
This attenuates the 45 kHz interrogation pulse while allowing the 35 kHz response
pulse through without much loss.
Figure 18 – 8th Order Filter Circuit
34
Figure 19 - 35 kHz Filter Response
As with the front-end amplifier circuit, an op-amp and digital potentiometer
is used for the post gain amplifier (see Figure 20). A Maxim Max412 op-amp was
used for the post-amp. This op-amp is low-noise and contains two op-amps. One
op-amp is used for the amplifier, the other for a voltage converter which is
discussed later. The same 5436 digital potentiometer is used in a manner identical
to the first stage amplifier. This circuit also has the same gain capabilities given
that resistor R7 is the same value as R63 from previous.
35
Figure 20 – Post Gain Amplifier Circuit
A LM567 IC is utilized to perform the tone decoding. This chip accepts an
AC input signal and connects the output terminal to ground when a tone of the set
frequency is detected. The typical application circuit from the datasheet was used
with only a few value changes to set the detection frequency and bandwidth (see
Figure 21). R134 is a manually adjusted potentiometer that is used to fine tune the
peak detected frequency. C76 sets the bandwidth. The value of C76 was chosen
such that the bandwidth of detection was set to approximately 10% of the center
36
frequency. This results in a bandwidth of approximately 3.5 kHz. An LED was
added to provide a visual indication when valid signals are received.
Figure 21 – Tone Decoder Circuit
Lastly, the microcontroller is used to detect the differences in the time of
arrival of the response pulse from the 3 transducers in the array. The
microcontroller used for this application is a Microchip dsPIC 33FJ128GP306
(shown in Figure 22). This microcontroller was chosen for its speed (up top 40
MIPS), abundance of on-board peripherals and digital signal processing capability.
The fast instruction cycle time, 25ns, provides the necessary time resolution needed
to discern small changes in the diver’s position. The on-board peripherals such as
SPI and ADCs allow for communication with other circuit boards and the ability to
add Auto Gain Control (AGC) respectively. Being that this microcontroller is in
37
fact a Digital Signal Processor (DSP) as well, it has the capability to provide signal
filtering and data processing which will be useful in future revisions of this device.
Figure 22 – Acoustic Processor Circuitry
2.5.1.4
Saving the Captured Data
In order to save data collected from various sensors for post processing, a
Secure Digital (SD) card data logger was used. The Logomatic V1.0 from Spark
Fun Electronics was chosen for its ease of integration, FAT16 file format and low
cost. Data is sent to the Logomatic via an asynchronous serial interface similar to
38
that used by a computer’s serial port. The data sent is stored in a computer
readable text file which can be downloaded to a PC via a card reader.
The schematic for the Logomatic (shown in Figure 23) has a few
mentionable devices in it. The ADG801 is an electronic switch that allows the
microcontroller to switch power to the Logomatic on and off. This can be used to
save power when the Logomatic is not in use. Two transistors are also used to
electronically activate the pushbuttons on the Logomatic. One button stops the
logging and closes the created data file. The other pushbutton resets the
Logomatic. This is used to begin logging data after it has previously been stopped.
Figure 23 – Data Logger Circuit
2.5.1.5
User Interface
Three methods of user interface were designed into the buoy electronics.
These include Bluetooth, RS-232 and I2C. A Bluetooth connection provides the
39
most efficient interface because it is fast and wireless. The Bluetooth interface
allows for a quick method of obtaining and setting various system parameters
without opening the casing of the buoy electronics. The RS-232 interface is the
same as the Bluetooth interface except that it requires a 9-pin serial cable between
the buoy electronics and the computer. The I2C interface was designed to connect
to a separate user interface circuit board. This board would be fitted with an LCD,
a few LEDs and some pushbuttons. This interface would require the user to be at
the buoy and would not be as efficient as the other two interfaces, however, no
computer would be required.
The design of the Bluetooth interface incorporates a module purchased from
Spark Fun Electronics. An LED was added to visually indicate an active Bluetooth
connection. A pull-up resistor was used on the reset line while a pull-down resistor
was used on PIO4 (as shown in Figure 24) as per the datasheet.
Figure 24 – Bluetooth Circuit
40
The RS-232 interface (shown in Figure 25) uses a standard 9-pin connector
and a MAX3233E. The MAX3233E IC translates the voltage levels between the
microcontroller and the computer. The resistors in the circuit limit the amount of
current in the event of a short circuit. Several jumpers are also installed in the RS232 circuit. These are used to direct communication with the computer between the
microcontroller and the GPS unit. These jumpers are generally installed to allow
communication with the microcontroller but can be switched to allow for
differential corrections to be sent to the GPS.
Figure 25 – RS232 Circuit
Two ADG804 multiplexers are used to route serial data transmissions to
and from the microcontroller. These are necessary since the microcontroller only
provides two serial interface ports. One of the two ports was dedicated to GPS
communications, leaving one available port to be shared by the data logger,
Bluetooth communication and RS-232 communication. Since only the RS-232 or
41
Bluetooth communications are used at any single time, the RS-232 communication
is connected unless an active Bluetooth connection exists. The data logger
connects only when the microcontroller is sending data for logging, resulting in no
loss of function with minimal hardware and software.
2.5.2 Diver Carried Transponder
Transponder electronics were designed to accomplish two tasks:
determining when a signal from the buoy is received and sending out a response
pulse. The circuits used to accomplish these tasks are almost mirror copies of those
from the buoy electronics with a few exceptions.
2.5.2.1
Detecting a Interrogation Pulse
The interrogation pulse detection circuitry varies slightly from the response
pulse detection circuitry described in Section 2.4.1.3. The primary difference is
frequency. The interrogation pulse has a frequency of 45 kHz as opposed to the 35
kHz response pulse. Detection of the interrogation pulse requires that the band
pass filter’s center frequency as well as the tone decoder’s detection frequency be
45 kHz. Both of these changes were implemented with simple component value
changes which were calculated with formulas provided by the component’s
datasheet. The response of the band pass filter is shown in Figure 26. The
microcontroller used on the transponder is a dsPIC33FJ12GP202. This
42
microcontroller is in the same family as the one used on the buoy electronics,
however, it is cheaper as it has fewer features and I/O pins.
Figure 26 - 45 kHz Band Pass Filter Response
2.5.2.2
Sending a Response Pulse
The transmit circuitry for the response pulse generator is essentially the
same as the interrogation pulse generator, however, the frequency of the response
pulse is 35 kHz. This frequency is controlled by a software delay on the
microcontroller and required no hardware change although a cheaper
microcontroller is used. This is the same microcontroller used to detect the
interrogation pulse.
43
2.6 Microcontroller Software
The BADNeS is comprised of three separate circuit boards, each containing
its own microcontroller. These microcontrollers do their part to determine the diver
position by running individual software. The main processor and the acoustic
board processor are located on the surface buoy while the transponder processor is
in the handheld diver unit.
The purpose of the main processor is to control all the sensors and store the
data. As shown in Figure 27, the microcontroller waits for the PPS pulse output
from the GPS before collecting data from the sensors. This provides a consistent
time base for the measurements and also ensures that data is only collected when
the GPS has positioning capability. After receiving the PPS pulse, the
microcontroller communicates with each sensor via several standard
communication protocols such as RS232, I2C and SPI. The sensors are instructed
to collect a measurement and when the data is ready the measurements are read into
the microcontroller. A time-stamp is collected prior to each measurement so that
latency can be examined. After all sensor measurements have been collected the
data is stored on an SD card for post-processing. This cycle starts again upon
reception of the next PPS pulse.
The acoustic processor handles the underwater acoustic tasks of the surface
buoy unit. The flow chart representation of the acoustic processor software is
44
shown in Figure 28. After initialization, the acoustic processor sits idle until it
receives a command from the main processor. The flow chart shows two such
commands. The “set parameter” command allows the user to change calibration
values. The “get measurement command” is used to obtain the range and bearing
of the diver unit. When this command is issued, the acoustic processor sends out
an interrogation pulse and starts a timer. If no response pulse is heard within the
specified “big timeout” period then the processor will return an error condition to
the main board and await another command. The timeout detection prevents the
processor from locking up when no transponder is within range. If a response
signal is received at any one of the transducers then a “small timeout” is set. The
“small timeout” setting ensures that the processor will not lock up when only one
or two of the transducers detect the response pulse. As with the “big timeout”, an
error is sent to the main processor and the acoustic processor await another
command. If all the transducers receive the response pulse, the data collected is
sent to the main processor. The acoustic processor then awaits another command.
The processor in the diver carried transponder carries out a basic function as
diagrammed in Figure 29. Upon reception of an interrogation pulse, the
transponder responds with a response pulse and then waits for the next
interrogation pulse.
The software was written and programmed into the microcontrollers using
the manufacturer’s development tools. The dsPIC series of microcontrollers made
45
by Microchip Technology Inc. were used as mentioned in Section 2.6. The software
was programmed in assembly language, compiled and uploaded using the MPLAB
IDE v7.60 development suite in conjunction with the ICD2 development tool.
MPLAB IDE was available for free from Microchip’s website
(http://www.microchip.com), while the ICD2 was purchased from Microchip.
46
Main Buoy
Processor
Initialize
Everything
No
New PPS Received?
Yes
Time Stamp
AP_STIME
Send Get
Measurement
Command to
Acoustic
Processor (AP)
Time Stamp
MAG_TIME
Collect
Magnetometer
Reading
Time Stamp
TILT_TIME
Collect Tilt
Readings
Read AP
Measurement
When Ready
Time Stamp
AP_ETIME
No
User Request Data
Collection?
Yes
Store Readings on
SD Memory Card
Figure 27 - Main Buoy Processor Flow Chart
47
Acoustic
Processor
Initialize
Everything
Has a command
been received?
Yes
No
Get Measurement
Command?
No
Set Parameters
Command?
Yes
Setup Big Timeout
Set the received
parameters
Send Interrogation
Pulse
No
Yes
Has Response
Pulse Arrived
Yet?
Has Big
Timeout
Occurred?
Set Small
Timeout
Have All
Transducers
Received
Response?
No
Yes
No
Yes
Has Small
Timeout
Occurred?
Yes
Send Partial Signal
Return Condition to
Main Board
Send Data back to
Main Board
Perform No Signal
Return to Main
Board
Figure 28 - Acoustic Processor Flow Chart
No
48
Transponder
Processor
Initialize
Everything
Has an Interrogation
Pulse Been Received?
No
Yes
Send a Response
Pulse
Figure 29 - Transponder Flow Chart
2.7 Transducers
An important part of the SSBL system is the acoustic array which is formed
by multiple transducers. Several factors influenced the design of the transducers
and the acoustic array. These factors are discussed as well as the procedures used
to build the array.
2.7.1 Environmental Factors Affecting Transducer Design
Several environmental factors affect the transmission of sound through
water. The factors which were found to be pertinent at the operating frequency
49
range of 35 – 45 kHz were examined prior to designing the transducer and are
discussed in this section.
2.7.1.1
Background Noise
Several factors in the ocean environment contribute to background noise
which must be taken into consideration for the underwater acoustic system design.
For a frequency range of 35 – 45 kHz, the following noise sources are relevant:
surface noise, noise from rain and noise from marine mammals.
Surface noise is noise induced by wave action at the surface. Figure 30
shows a plot of surface noise for various sea states plotted versus frequency.
Assuming recreational diving would not be common in sea states greater than 4
(approximately 1.2 meter waves), then the surface noise will be 42 dB (Waite,
2002) maximum.
50
Figure 30 - Background Noise Levels (Waite, 2002)
Rain, although intermittent, can dominate as the lead source of noise given
heavy rain conditions. Figure 31 shows a plot of rain induced noise versus
frequency for several different rainfall rates. At a rain range of 30 to 100 mm/hr,
the rain induced noise level is approximately 60 dB. When rain induced noise is
combined with surface noise using incoherent addition, the overall noise level is
still approximately 60 dB. Thus, when a heavy rain occurs, the background noise
will be at its greatest, 18 dB greater than when it is not raining.
51
Figure 31 - Noise Due to Rain (Waite, 2002)
The last source of background noise is echolocation from marine mammals
such as dolphins. Typical echolocation frequencies range between 50 – 200 kHz.
Although these sounds are outside the range of interest, echolocation clicks can
reach levels as high as 200 dB (Lurton, 2002). At these high levels, there is a
chance that some lower frequency energy will affect the super short base line
measurements. For this project it will be assumed that marine mammals are not
contributing to the background noise affecting the BADNeS.
52
2.7.1.2
Reverberation
Reverberation is the return of sound back to the source from anything other
than the transponder (Lurton, 2002). Reverberation was considered during the
design of the BADNeS so it would not cause a problem. Two possible
consequences of reverberation are 1) picking up the interrogation signal on the
buoy’s receivers rather than picking up the response signal and 2) picking up multipath reflections of the signal. In the first case, the receivers are set to listen too
soon causing them to pickup the interrogation signal. This problem can be solved
by a simple delay, or in the case of the BADNeS, separate interrogation and
response frequencies can be used. The second problem is solved by the use of two
different frequencies as well. If a single frequency was used, a reflection of the
interrogation signal could bounce off a nearby object and reach the buoy’s receivers
well before the response pulse. This would effectively make the diver appear to be
located at the object causing the reflection. Since two separate frequencies are
used, the first signal to reach the transponder will be the original interrogation pulse
since reflected signals will incur longer travel times. The transponder will not
respond to signals picked up shortly after the original interrogation pulse as it will
be transmitting a response pulse. The same logic applies to the returned response
pulse. Thus reverberation should not be a problem.
53
2.7.2 Transducer Design Parameters
The transducer design parameters were derived from the desired
functionality of the BADNeS system. The design parameters established were
frequency, bandwidth, beam pattern and power output / sensitivity.
Two different frequencies were used for the interrogation and response
pulses for reasons discussed in Section 2.6.1.2. The use of two separate
frequencies was recommended by Lee Frey, a Florida Institute of Technology
master’s degree graduate, after his experience with an acoustic compass. The two
frequencies chosen were 35 kHz and 45 kHz. These were chosen because they are
not heard by divers, have relatively low loss over short distances and are different
enough in frequency to be discerned from one another.
For a narrowband application such as this, the bandwidth should be the
reciprocal of the transmit pulse length (Waite, 2002). Assuming a pulse length of 1
millisecond, a 1 kHz bandwidth would be appropriate.
The ideal beam pattern for this application is a hemi-spherical beam pattern.
This would allow the buoy and transponder to communicate regardless of the
diver’s position in reference to the buoy. The only restriction being that the diver
must be at or below the depth of the transducers on the buoy.
The required transducer power output / sensitivity was calculated by
predicting spreading and absorption loss then adding the predicted background
54
noise. Assuming a 45 kHz maximum frequency and a maximum distance from the
buoy to the diver of 100 meters the losses were calculated to be:
Spherical Spreading Loss = 20 × log(r ) = 20 × log(100) = 40.0dB
(
Absorption Loss = α × D = (0.05 × f 1.4 )× D = 0.05 × (45)
1.4
[3]
100 
)×  1000
 = 1.0dB [4]


Propagation Loss = Spreading Loss + Absorption Loss = 40.0 + 1.0 = 41.0dB [5]
(Waite, 2002)
Where:
r
α
D
f
= Radius in meters
= Absorption coefficient approximation in dB per km (sea water)
= Distance of travel in km
= Frequency of sound in kHz
Adding the propagation loss to the background noise gives an approximate
minimum figure for transducer power output. For this system the minimum
required power output varies from 83 – 101 dB depending on rain condition. In
practice, however, the transmitted power level should be greater than this figure so
that the signal to noise ratio is greater than 1.
2.7.3 Transducer Design
At the inception of this project, commercially available transducers with the
design parameters previously described were to be used for the prototype.
However, after researching the available transducers, none were found that suited
the application. In addition, the commercially available transducers found that
matched the design specifications the closest were prohibitively expensive (greater
55
than $1,000 each). Since the prototype unit requires six (6) transducers, cost alone
was a limiting factor. Therefore, the transducers had to be constructed in an
economical fashion. A future revision of the prototype should incorporate properly
designed transducers which when mass produced would become economical.
In order to construct six (6) transducers in a short period of time with a
small budget, only very basic design principles were utilized in the design. The
NonDestructive Testing (NDT) Resource Center was found to contain the basic
design formula needed for the task. A transducer has the following basic parts: a
backing, an active element and a matching layer (NDT Resource Center, 2008).
These parts are shown in Figure 32 along with the ideal thicknesses of both the
active element and the matching layer.
Figure 32 - Basic Transducer Design (NDT Resource Center, 2008)
The active element should be a half-wavelength thick for maximum energy
transfer. The matching layer provides an acoustic impedance match between the
active element and the water. In order to provide this, the matching layer should be
56
comprised of a material with acoustic impedance between that of the active element
and water. It should also be a quarter-wavelength thick in order to keep any
reflected waves in phase.
The backing layer affects the bandwidth of the transducer. Choosing a
backing layer with similar acoustic impedance as the active element produces a
transducer with a wide bandwidth. A mismatch in the acoustic impedance causes
the bandwidth to narrow. Since this application requires narrow bandwidth and no
exact equations for calculating the bandwidth versus acoustic impedance mismatch
were given, the selection of the backing layer was deemed not critical. Ultimately,
stainless steel was used for a backing layer.
Off the shelf piezo elements were used for the active element. A large
supply of extremely low-cost piezo elements were found by a previous Florida
Institute of Technology graduate student, Mischa Dembicki. Although these
elements weren’t ideal, they were used in the interest of saving time. By using
non-ideal piezo elements, efficiency is lost in the transfer from electrical energy to
acoustic energy and vice-versa.
The matching layer was designed to be a quarter-wavelength thick and have
acoustic impedance between water and the active element. Assuming a speed of
sound in seawater of 1500 m/s, the wavelength of a 40 kHz signal (mean of 35 kHz
and 45 kHz) is calculated to be:
57
λ=
c 1500m / s
=
= 0.0375m
f 40000 Hz
[6]
Where:
λ
c
f
= Wavelength in meters
= Assumed speed of sound in water in meters per second
= Frequency of sound in Hz
Dividing this result by four, results in a matching layer 9.4mm thick. The acoustic
impedance (Z) of a material is calculated by the following formula:
Z = pV
[7]
Where:
Z
p
V
= Acoustic impedance in Pascal seconds per meters
= Material density in kilograms per meters cubed
= Velocity of sound through the material in meters per second
Since the acoustic impedances of most materials are not published (as well as the
velocity of sound through them), the following logic was used to determine the
matching layer material. If it is assumed that the acoustic impedance of a material
is determined by density, then a material with a density between water and the
piezo element should suffice. The density of seawater is known to be
approximately 1,035 kg/m3. The density of a piezo-ceramic element is
approximately 7,600 kg/m3 (APC International Ltd., 2006). Since the transducer
had to be potted anyways, epoxy resin makes a practical matching layer. For West
System Epoxy Resin type 106/206, the density is 1180 kg/m3 (Gougeon Brothers,
Inc., 2007). This density may not provide for the best matching layer but it is
within the acceptable limits according to the basic design.
58
Ideally the transducer design would be tested for its power output /
sensitivity by simulation or prototype testing. Both of these methods require
extremely specialized software / equipment not readily available, therefore, the
actual power output / sensitivity of the transducers remains unknown.
2.7.4 Array Design
An array of transducers is needed to determine the azimuth and heading of
the transponder from the buoy. An incremental approach was taken to determine
the number of transducers required in the array. If the array is constructed with
only one transducer, no directional information could be ascertained as shown in
Figure 33.
Water Surface
Transducer
Possible
Transducer
Transponder
Positions
Bottom View
Side View
Figure 33 - Single Transducer Array
If an array consisting of two transducers oriented in a line is used,
directional information would be available, however, some ambiguity would still
59
exist. Figure 34 shows two pairs of transducer positions that would appear
identical to the array processor. The black circles represent one set of identical
looking positions while the grey circles represent another possibility.
Possible
Transponder
Positions
Water Surface
Transducers
Bottom View
Transducers
Side View
Figure 34 - Two Transducer Array
If an array consisting of three transducers arranged in an equilateral
triangular is used, no directional ambiguity will exist as shown in Figure 35. This
arrangement places the water surface above the array. Without this boundary, an
ambiguity as to whether the signal arrived above or below the array would exist.
60
Water Surface
Transducers
Transducers
Side View
Bottom View
Figure 35 - Three Transducer Array
More transducers can be added to the array to increase the accuracy, however, this
also increases the complexity and cost. It is for these reasons that the three
transducer array design was chosen.
For the three transducer array to work the transducers must be arranged in
an equilateral triangle. This requires that the transducers are arranged at 120
degrees angles from one another at the same distance from a central point. The
actual distance from the central point isn’t critical so long as the distance is
sufficiently large to produce a noticeable time difference for small changes in
transponder position. Matlab was used to simulate the time of arrival differences
between the three receiving elements. The angle at which the transponder was
offset from the transducer array was changed by one degree and the difference in
relative arrival times was noted. With a central point to transducer distance of
0.254 meters and a detection time of 25 nanoseconds, a 0.1 degree resolution is
61
achievable in an ideal world. With the transponder at a distance of 60 meters from
the buoy this translates into a linear distance error of less than 0.2 meters. This is
more than sufficient given the accuracy of the GPS position. Therefore, the central
point to transducer distance specification for the prototype was set at 0.25 meters or
greater.
3 Construction
Many pieces were custom fabricated for this prototype. Methods used to
create the components making up the final prototype are discussed in the following
sections. It should be noted that in a mass produced version, different construction
techniques would be employed.
3.1 Electronics
The construction of the electronics presented a few challenges, mainly due
to the small size and close proximity of the components. The first challenge was to
build the required circuit boards with extremely tight tolerances. Solder paste then
had to be placed on all the pads and the respective SMD components positioned on
top. The board then had to be heated so that the SMD connections were soldered.
Finally, the thru-hole components were soldered using standard techniques.
A professional board house was used in order to obtain circuit boards with
the required tolerances. The company Advanced Circuits was chosen as the
62
supplier because of customer recommendations, their more then sufficient
capabilities and the great student discount. The CAD files for each of the circuit
boards were uploaded via Advanced Circuits website. Two weeks later the boards
arrived as designed and for only $45 per board (including shipping).
The next task was to cover all the SMD component pads with a thin layer of
solder paste. Zephpaste by Zephyrtronics was used as the solder paste. This paste
dispensed out the tip of a needle mounted to a syringe when pressure was placed on
the syringe’s plunger. A variety of needle sizes were tested until one was found
that produced a small dot of solder paste without an extraordinary amount of
applied pressure. Normally stencils would be used to apply the paste to the
required areas; however, getting a stencil made for each board isn’t economical for
just one board. Instead of stencils, steady hands, patience and a little trick was
used. The paste was carefully placed by a stead hand on each individual pad (see
Figure 36). For the pads which were too small and too close together to place
individual beads of paste, a trick was devised. Each row of small, tightly spaced
pads was coated with one single bead of solder paste. A soldering iron was then
run over the pads. This melted the paste and forced it to split itself up among the
pads. These pads were then inspected for solder bridges which were removed if
found.
63
Figure 36 – Transponder Board With Solder Paste
With the solder paste placed, the SMD components then had to be placed.
The trick to this was a good pair of tweezers. Each component was identified,
checked for orientation and then placed gently on top of its pads (see Figure 37).
The board was sitting on top of a turn table which helped during this step.
Figure 37 – Transponder Board After Component Placement
The last SMD step was to heat the solder paste until it reflowed, electrically
and physically bonding the SMD components to the circuit board. An ingenious
method for doing exactly this was outlined on Spark Fun Electronics Website
64
(Sparkfun Electronics, 2006). This method involved pre-heating a store bought
skillet to its maximum temperature of 400 °F. The circuit board was then placed
(component side up) on the hot skillet using small bits of wire tied to the corners of
the board. The board was allowed to sit until the reflow of the solder paste was
observed. It was required that the board was moved around in order to get all the
components to reflow. The wires were then again used to gently lift the board off
the skillet and place it on the ground to cool.
The thru-hole components were soldered to the circuit board using
traditional techniques. This involved first placing the components. Next, a
soldering iron was used to heat the component lead, pad and a bit of solder. The
soldering iron was then removed when the solder had flowed between the
component lead and pad. Finally, any protruding component leads were trimmed.
The final board is pictured in Figure 38.
Figure 38 – Finished Transponder Board
65
3.2 Transducers
The transducers were constructed according to the design outlined in
Section 2.6.3 and a few other considerations. The design requires that a measured
thickness of resin be over top the piezo element and a piece of metal be directly
behind the piezo element. Mounting considerations require that a screw thread
come out the back of the transducer and common sense requires that all the
electrical connections be waterproof. The sensors should also be small so as to not
require much resin. The following steps were taken in building each transducer:
Note: Since this unit was constructed in the U.S.A, items and tools were used which
were sized according to standard units. In order to avoid confusion in the event
these instructions are used, the measurements have not been converted to metric.
1. A template was used to mark the center of a 1 inch PVC pipe cap (see Figure
39). A sharp pointed tool was then used to make an indentation on the plastic
cap.
66
Figure 39 - Drill Template
2. A drill was used to make a quarter inch hole in the center of the pipe cap (where
the mark was placed) as shown in Figure 40. It was discovered that a pre-drill
step with a small bit was required prior to using the quarter inch drill bit to
accurately position the hole.
Figure 40 - Drilling Screw Hole
67
3. A hole was drilled in the side of the plastic cap towards the bottom (see Figure
41). This hole is the entry point for the wire and was drilled so as to be just
large enough. Pre-drilling would also be advised for this step.
Figure 41 - Hole for Wire
4. The wire was fed through the side hole and soldered to the piezo element. The
soldered connections were covered with heat shrink tubing to avoid a short
circuit (see Figure 42).
Figure 42 - Soldering Wires to Piezo Element
68
5. A quarter inch stainless steel screw with a nut threaded on it was placed into the
hold in the bottom of the cap. The nut and head of the screw were installed
inside of the cap as shown in Figure 43.
Figure 43 - Screw in Cap
6. A stainless steel washer was placed on top of the screw head and the piezo
element was glued to the center of this washer (see Figure 44). A quick setting
super glue was used for this step. The orientation of the piezo element was
such that the metal surface was in contact with the washer while the actual
piezo material was facing upwards.
69
Figure 44 - Piezo Element Glued to Washer
7. The height of the piezo element from the top of the cap was adjusted such that
it conformed to the design. The depth measurement portion of a dial caliper
was used to make the measurement as shown in Figure 45. Adjustments were
made by turning the screw while pressing the nut against the cap bottom.
Figure 45 - Measuring Piezo Height
8. The assembly was prepared for pouring. The wire was glued so that only
insulation was showing on the outside. The washer was placed at an angle on
top of the screw head so as to allow resin to first flow to the bottom of the cap.
The screw protruding from the bottom of the cap was used to secure the whole
assembly to a rigid base. A second nut was then threaded on to lock the
assembly into place.
70
9. The epoxy resin was prepared. The resin used was a two part West System
epoxy resin: type 105 resin and type 206 hardener. The resin and hardener were
measured according to the directions and mixed thoroughly.
10. The resin was poured into the caps. Once enough resin was poured such that
the area below the washer was full, the washer was rested on the screw head.
More resin was poured until it reached the top of the cap (see Figure 46). As
the resin set up the caps were monitored. Any air bubbles were removed using
a toothpick to bring them to the surface.
Figure 46 - After the Resin Pour
3.3 Buoy
The buoy was required for two purposes, to float the GPS unit and to mount
the transducers. The GPS unit has to be above the surface of the water and have an
unobstructed view of the sky. The transducers have to be mounted so that they are
submerged and have an unobstructed view of the transponder. They also have to be
71
mounted in such a way as to meet the acoustic array design criteria specified in
Section 2.6.4.
The base of the buoy was constructed from an inner tube and some wood.
The inner tube was picked up from a local tire shop and selected such that its outer
diameter was approximately 0.6 meters. This size was selected because it is
slightly bigger than the acoustic array so as to provide protection and still be small
enough to fit easily on a dive boat. A bit of plywood was cut into a circle roughly
the size of the inner tube. A few 2 by 4’s were then screwed into the plywood and
cut such that a pelican case could be secured. The pelican case was used to house
the buoy electronics including the GPS unit. A series of holes were drilled around
the outside of the wooden base. The majority of holes were made to secure the
base to the inner tube. The other two holes were made for transducer wires to run
through to the center of the buoy. After the wooden base was finished, it was
coated in epoxy resin in order to waterproof it. The base was then painted and
secured to the inner tube with bungee cord as shown in Figure 47.
72
Figure 47 – Buoy With Electronics Box
The transducer mount was constructed out of aluminum. Aluminum was
chosen for three key factors: strength, rigidity and being non-ferrous. Strength is
required since the entire weight of the buoy rests on the mount when it isn’t in the
water. Rigidity is required to keep the transducers from moving relative to the GPS
antenna and one another. The mount needs to be non-ferrous so as to not interfere
with the magnetometer mounted atop the buoy. The mount was built by welding
some bits of flat aluminum stock to a central aluminum tube. The flat aluminum
pieces were cut and welded so as to adhere to the transducer array design
calculations. After welding these it was discovered that the flat bar could bend
rather easily so a few supporting members were added. A mounting plate was then
welded to the opposite end of the central tube. Finally, four holes were drilled into
the mounting plate. The finished mount is pictured in Figure 48.
73
Figure 48 – The Acoustic Array Mount
The transducer array mount was attached to the underside of the wooden
base. This was accomplished by using screws to secure the mounting plate on the
transducer array to the underside of the wooden base. The array was mounted in
the center of the wooden base with an arbitrary orientation. The orientation doesn’t
matter so long as it is known. The final constructed buoy is shown in Figure 49.
Figure 49 – Final Constructed Buoy
74
3.4 Diver Unit
Figure 50 - Diver Carried Transponder
The diver carried transponder (shown in Figure 50) was constructed out of a
3250 Series Otter Box. This polycarbonate housing has ample space for the
batteries, electronics and transducers and is also rated to 30 meter (100 foot) water
depth (Otter Products, LLC., 2008). The batteries and electronic circuit board were
secured by use of double-sided adhesive strips.
The transducers for the transponder were molded to the top of the housing.
Steps similar to that described in Section 3.2 were used to accomplish this. Instead
of West System Epoxy Resin, a 3M Marine Adhesive Sealant (type 5200) was
used. 3M 5200 Sealant was used because it doesn’t generate a lot of heat like the
West System Resin. Excessive heat could warp the polycarbonate housing and
compromise its structural integrity.
75
4 Calibration
Before the BADNeS could be used some calibration parameters had to be
measured. These calibration parameters are required to correct the raw
measurements and calculate the diver’s absolute location.
4.1 Offsets
Several offsets must be known to reference the transponder position to the
GPS datum, WGS84. Figure 50 shows the required offsets. Offset A and D are the
GPS antenna’s center offset from the center of the SSBL array. Offset B is the
vertical offset of the GPS antenna from the SSBL array. Offset C is the distance of
the SSBL transducers from the center of the array. The offset angle of the acoustic
array and the magnetometer is also required.
A
Interrogation
Transducer
C
GPS Antenna
A
B
D
C
C
GPS Antenna
Receiving
Transducers
Transducer
C
Top View
C
Side View
Bottom View
Figure 51 – Offsets Required to Reference Transponder Position to Buoy Position
76
4.2 Tilt
The tilt sensor must be calibrated before use to remove any tilt angle present
in the sensor mounting. The calibration procedure requires that the SSBL array is
level in both the pitch and roll axes. The sensor calibration command is then sent
to the tilt sensor. This command instructs the sensor to measure the tilt and save it
as an offset. Every raw measurement following the calibration will have this offset
subtracted from it.
4.3 Heading
By performing a simple calibration, the direction of magnetic north and thus
the buoy’s heading, can be deduced. The calibration procedure described in PNI
Corporation’s multipoint calibration application note requires that data from the
magnetometer be collected while it is rotated slowly a full 360 degrees. An
example of this collected data is shown in Figure 51.
77
Figure 52 – Example calibration data (PNI Corporation, 2004)
From the data collected the maximum and minimum X and Y values are
determined. Two offsets and two gains are then calculated via the following
formulas:
Xoffset = ( Xmax + Xmin ) / 2
Yoffset = ( Ymax + Ymin ) / 2
Xrange = ( Xmax – Xmin )
Yrange = ( Ymax – Ymin )
[8]
[9]
[10]
[11]
The offsets and gains are applied to the raw data by the following method (see
Figure 52):
1) Subtract the offsets.
Xvalue = Xraw – Xoffset
Yvalue = Yraw – Yoffset
2) Scale the data.
If Xrange > Yrange Then,
[12]
[13]
78
Yvalue = ( Yvalue * Xrange ) / Yrange
Else,
Xvalue = ( Xvalue * Yrange ) / Xrange
[14]
[15]
Figure 53 – Data after offsets are applied (PNI Corporation, 2004)
79
Figure 54 - Calibrated Magnetometer Output
Figure 53 depicts the expected magnetometer output after calibration for various
values of heading with respect to magnetic north. The heading is computed from
the calibrated X and Y values by the following method:
1) Calculate A in degrees.
A = arctan( Xvalue / Yvalue)
[16]
2) Find the heading based upon the quadrant.
If X >= 0 & Y >= 0 Then, Heading = Angle + 270
If X < 0 & Y >= 0 Then, Heading = Angle + 270
If X < 0 & Y < 0 Then, Heading = Angle + 90
If X >= 0 & Y < 0 Then, Heading = Angle + 90
[17]
[18]
[19]
[20]
80
While only two-axes are needed to determine heading, data from the third axis
could be used for additional heading correction when roll and pitch are severe.
4.4 Electronic Delay
Electronic delay affects both the range and bearing measurements of the
acoustic processor by increasing the time of arrival at the transducers. The delay
originates from a propagation delay in the electronic filter and amplifiers. This is
present in both the transponder electronics and the acoustic processor electronics.
To find out the electronic delay present in the path of each receiving transducer, the
transponder is placed at a known depth directly below and in the center of the
SSBL array. The acoustic processor is issued a get measurement command and the
arrival times at each transducer recorded. An accurate speed of sound
measurement should be taken shortly before or after this measurement is taken.
Post-processing is then performed to find the delay present in the arrival time of
each transducer’s measurement by subtracting the estimated roundtrip travel time
from each arrival time. These calculated delays are the electronic propagation
delays and should be subtracted from the arrival times on all subsequent
measurements. It should be noted that each transducer will experience a unique
propagation delay. While all the circuitry is the same for each receiving element,
tolerances in component values affect signal propagation causing unique delays.
81
5 Post Processing
Post processing is used in order to calculate the final position of the
transponder given raw measurements from the GPS, orientation sensors and
acoustic array. The following steps are taken during the post-processing:
1) Compute the Range (R) of the transponder from acoustic array. The
range is computed using the roundtrip travel time of sound from the buoy to
the transponder and back. The following formula is used:
 T 

R =  RT  − Delay  × C avg
 2 

[21]
Where:
Range = Distance from transducer to buoy in meters
= Round trip travel time in seconds
TRT
Delay = Calibration coefficient to make up for any delays in travel time
Cavg
measurement given in units of seconds.
= Measured or assumed average velocity of sound in water given in units
of meters per second.
2) Compute the Elevation Angle ( β ) and Heading Angle ( α ) of the
transponder from the acoustic array. The elevation and heading angles
are computed using the difference in arrival time between the three
transducers making up the acoustic array. These are computed with the
following formulas (see the corresponding diagram in Figure 54):
 ∆T 
α =  bc  × 60° + A
 ∆Tac 
[22]
82
For odd-numbered zones (1,3,5)
 ∆T 
 × 60° + A

α =  ab
 ∆Tac
[23]
For even-numbered zones (2,4,6)
 ∆Tac 

∆
T
 ac max 
β = cos −1 
[24]
Where
∆Tab
= Time difference between the first and second transducers to detect the
∆Tbc
signal.
= Time difference between the second and last transducers to detect the
∆Tac
signal.
= Time difference between the first and last transducers to detect the
signal.
∆Tac max = Maximum time difference between the first and last transducers to
A
detect the signal.
= Lower angle limit of the zone (e.g. for Zone 5, A = 240)
(Frey, 2003)
83
Figure 55 - Wave Propagation Over the Acoustic Array (Frey, 2003)
84
3) Using the orientation sensors and measured offsets, determine the
offset of the transponder from the buoy in Cartesian coordinates.
4) Convert the GPS coordinates of the buoy to Cartesian coordinates. The
conversion from GPS coordinates to Cartesian coordinates is performed
with the following formulas:
X GPS = (v + h ) × cos(φ ) × cos(λ )
[25]
YGPS = (v + h ) × cos(φ ) × sin(λ )
[26]
(
)
Z GPS = (v × 1 − e 2 + h ) × sin(φ )
[27]
(Misra, 2004)
Where:
X GPS = X Cartesian coordinate of GPS position in meters
YGPS = Y Cartesian coordinate of GPS position in meters
Z GPS = Z Cartesian coordinate of GPS position in meters
φ
λ
h
= GPS latitude in degrees
= GPS longitude in degrees
= GPS height above the ellipsoid in meters
v =
(1 − e
a
2
)
× sin 2 (φ )
1/ 2
[28]
= WGS84 ellipsoid semi major axis = 6,378,137.0 meters
a
2
e = WGS84 first ellipsoid eccentricity squared = 0.00669437999013
5) Add the offset of the transponder from the buoy to the GPS
coordinates.
85
X T = X GPS + X TB
[29]
YT = YGPS + YTB
[30]
Z T = Z GPS + Z TB
[31]
Where:
XT
YT
ZT
X TB
YTB
Z TB
= X Cartesian coordinate of the transponder (diver) in meters
= Y Cartesian coordinate transponder (diver) in meters
= Z Cartesian coordinate transponder (diver) in meter
= X Cartesian coordinate of the transponder offset in meters
= Y Cartesian coordinate transponder offset in meters
= Z Cartesian coordinate transponder offset in meter
6) Convert the transponder’s coordinates back to the WGS-84 coordinate
system. The conversion from Cartesian Coordinates to WGS-84 is
performed with the following formulas:
 YT
 XT
λT = tan −1 
hT =



[32]
p
− vT
cos(φT )
Z
φT = tan  T
 p

−1

 vT
1 − e 2 
v +h

T
 T

[33]

 


−1




[34]
(Misra, 2004)
Where:
φT
λT
= Transponder longitude in degrees
hT
= Transponder height above the ellipsoid in meters
= Transponder latitude in degrees
86
vT =
p=
(1 − e
a
2
× sin
2
(φT ))1 / 2
X T2 + YT2
[35]
[36]
Note: Iterations are required to find latitude and height to the required precision.
6 System Performance
The proto-type unit was tested to get an estimate of the overall system’s
positioning accuracy and precision. The system performance estimate was
obtained by finding the contribution of each sensor to the overall positioning error.
In order to do this, each sensor’s accuracy and precision had to be tested
individually. The testing procedure and results are described below along with the
final overall system performance estimate.
6.1 GPS Receiver
The GPS receiver was tested by placing its antenna at a known location and
logging its computed positions. The logged data was post-processed in MATLAB
to determine the accuracy and standard deviation of the GPS receiver in terms of
2D RMS positioning error. Since the accuracy of the GPS receiver depends on the
orientation of the GPS Satellites which vary with time and location, the GPS
receiver was tested at nine (9) different times and at two locations.
87
6.1.1
Data Collection
The GPS data was collected at two locations with known coordinates. The
first location was in the parking lot of Fugro West, Inc., a survey company in
Ventura, California. The location, known to Fugro West as “point 6”, was marked
by a nail head embedded in asphalt. The coordinates of point 6 were provided by
Fugro West, Inc. The provided coordinates were referenced to the original GPS
datum (original WGS 84) which differs slightly from the reference now used by the
GPS, WGS 84 (ITRF00). In order to transform the coordinates to the new
reference, the Horizontal Time Dependent Positioning (HTDP) utility available in
the Geodetic Tool Kit on the National Geodetic Survey (NGS) Website
(http://geodesy.noaa.gov/) was used. The second location was found using the
datasheets search on the NGS website. This search provided a list of known points
in the local area for which the NGS had datasheets. RINCON (PID: EW7931) was
chosen as a second test location due to its proximity to the ocean and its recently
noted good condition. The RINCON datasheet (see Appendix E) listed its
coordinates in the current WGS 84 epoch so no transformation was required.
The GPS receiver was positioned over the known location with a tripod
equipped with a tribrach. First the tripod was positioned over the known landmark
and roughly leveled. The tribrach was then adjusted to make it level and its optical
plummet positioned directly over the landmark as shown in Figure 53.
88
Figure 56 - Tripod with Tribrach Set Over Point 6
Figure 57 - Tripod with Tribrach Used to Position GPS Receiver Over Point 6
89
The GPS receiver’s antenna was then positioned directly over the known location
using the target on the tribrach’s optical plummet as shown in Figure 54. With the
GPS in place, the box containing the GPS was taped in place and the tripod
removed.
Data logging was performed by switching on the power switch to the buoy
electronics. The buoy electronics logged the GPS data to an SD card for postprocessing in MATLAB.
6.1.2 Data Processing
The data collected from the GPS receiver was imported into MATLAB and
compared against the coordinates of the known point to find the precision and
accuracy of the GPS receiver. The following steps were taken for each of the data
sets:
1) Both the known and logged GPS coordinates were converted from latitudes
and longitudes to Cartesian Coordinates (see Section 5 for this formula).
An elevation of 0.0 meters was used for the height.
2) The distance between each of the logged positions and the known position
was calculated using the distance formula. This distance is also the 2D
RMS positioning error.
2 D _ RMS _ Error =
(X K
− X L ) + (YK − YL ) + (Z K − Z L )
2
2
3) The average 2D RMS Error was computed and recorded.
2
[37]
90
4) The maximum 2D RMS Error was found and recorded.
5) The standard deviation of the 2D RMS Error was computed and recorded.
6) The fix type was recorded. The Standard Positioning Service (SPS) fix type
indicates a regular GPS position. The Differential fix type indicates the use
of a WAAS satellite to obtain differential corrections.
7) The duration of the data collected was also recorded.
8) Trimble Planning Software version 2.74 was used to obtain a predicted
Horizontal Dilution of Precision (HDOP). The HDOP is a unit-less
measure of GPS data quality based on the orientation of the GPS satellites.
Lower HDOP values indicate better satellite orientations and position
estimates. By entering the date, time, position and obstruction information
into the Trimble Planning Software, a list of HDOP values were output (see
Appendix E).
The results of the GPS Receiver testing are shown in Table 2.
91
Table 2 – GPS Receiver Testing Results
Location
Fugro
Point 6
Fugro
Point 6
Fugro
Point 6
Fugro
Point 6
Fugro
Point 6
Fugro
Point 6
RINCO
N
RINCO
N
RINCON
Date/Time
(P.S.T.)
12/26/2007
5:23 PM
12/26/2007
5:33 PM
12/27/2007
1:48 PM
12/27/2007
2:00 PM
12/28/2007
7:48 AM
12/28/2007
7:58 AM
12/29/2007
9:57 AM
12/29/2007
10:35 AM
12/29/2007
11:08 AM
Mean
2DRMS
Error
(m)
Max
2DRMS
Error
(m)
Standard
Deviation
(m)
Predicted
HDOP
Fix
Type
Record
Length
(min)
3.95
8.99
0.83
1.62
SPS Fix
10
4.69
6.78
0.58
1.58
SPS Fix
8
24.35
33.71
3.46
2.57
SPS Fix
11
13.78
18.63
1.65
2.35
Diff
9
5.16
8.33
1.77
1.36
SPS Fix
9
4.87
8.89
1.97
1.41
SPS Fix
7
2.86
4.27
0.86
1.05
Diff
32
3.92
4.59
0.31
1.44
Diff
32
5.88
18.23
3.61
3.21
SPS Fix
28
6.2 Magnetometer
Accuracy of the magnetometer was tested and verified with an S.G. Brown
TSS Meridian Surveyor Gyro. The devices were mounted on a fiberglass cart, to
prevent disrupting the magnetometer, as shown in Figure 55. This setup allowed
both devices to be rotated simultaneously. This ensured that the gyro and
magnetometer maintained a constant heading offset from one another. The gyro
has a listed accuracy of ±0.05 degrees (S G Brown, 2003) and outputs headings
referenced to true north. For this reason, the gyro’s heading was assumed to be the
actual heading.
92
Figure 58 - Magnetometer Testing Setup
6.2.1 Data Collection
Before a heading could be determined from the magnetometer output, a
magnetometer calibration had to be done as described in Section 4.3. Three
calibrations were performed to ensure that the results obtained could be reproduced.
The gyro heading was recorded at the start of each calibration in order to obtain the
heading offset between the gyro and the magnetometer. The offset was computed
by subtracting the magnetometer heading at the start of the calibration from the
gyro heading. The offsets computed for each of the three (3) calibrations are listed
in Table 3.
Table 3 - Computed Offsets
Calibration
Offset
Number
(degrees)
1
-12.9
2
-10.6
3
-37.6
93
After the magnetometer calibrations, data was collected at 24 degree
increments. Approximately ten (10) seconds of data from the magnetometer was
logged to an SD card at each heading while the gyro heading, which remained
constant, was read from its display and recorded. A sample of the data recorded
from the magnetometer is shown in Figure 56.
Figure 59 - Sample Heading Data
6.2.2 Data Processing
MATLAB was used to process the collected data. The heading error was
computed by subtracting the average magnetometer heading from the gyro heading
for each of the fifteen (15) data records. The heading error was computed using the
94
calibration parameters from each of the calibrations. The results are plotted in
Figure 57. The standard deviations were also calculated and found to vary only
slightly among the different calibrations. For this reason, only the standard
deviation values obtained using calibration two were plotted (see Figure 58).
Table 4 shows the average statistics for each of the calibrations.
Figure 60 - Plot of Heading Error
95
Figure 61 - Plot of Standard Deviation
Table 4 - Overall Heading Statistics
Mean Heading
Error (degrees)
Mean Standard
Deviation (degrees)
Calibration Calibration Calibration
1
2
3
-0.17
-0.53
0.16
0.12
0.13
0.13
6.3 Tilt Sensor
Accuracy of the tilt sensor was tested and verified with a CodaOctopus
F180 Attitude and Positioning System. The devices were mounted to a sheet of
plywood so that the change in tilt was the same for both devices as shown in Figure
96
61. The F180 was assumed to be the actual tilt as its listed accuracy is better than
0.025 degrees (CodaOctopus, 2008).
Figure 62 - Tilt Sensor Testing With CodaOctopus F180
6.3.1 Data Collection
Tilt sensor data was logged to an SD card and F180 data was read from a
computer display and recorded for various tilt angles. Small wood pieces were
placed under different areas of the plywood on which the tilt sensor and F180 were
mounted to create the various tilt angles.
6.3.2 Data Processing
MATLAB was used to process the collected data tilt sensor data (see Figure
59 for a sample tilt record). First, the X and Y tilt offsets between the tilt sensor
and the F180 were calculated. These offsets were then added to all of the tilt sensor
97
measurements. The X and Y tilt errors were computed by subtracting the average
tilt sensor readings from the F180’s roll and pitch readings for each of the various
tilt angles. The results are plotted in Figure 60. The standard deviations were also
calculated and plotted in Figure 61. Table 5 shows the average statistics for each of
the calibrations.
Figure 63 - Sample Tilt Data
98
Figure 64 - Mean Tilt Error
Figure 65 - Tilt Standard Deviation
99
Table 5 - Overall Tilt Sensor Statistics
X Tilt Y Tilt
Mean Tilt
Error (degrees)
Mean Tilt
Standard Deviation
(degrees)
0.05
0.00
0.30
0.29
6.4 Super Short Base Line
The SSBL portion of the BADNeS prototype was unable to be tested for
accuracy and precision due to a hardware problem discovered in the acoustic
processor. While tuning the three (3) tone decoders on the acoustic processor, a
coupling effect between the tone decoders was found. The problem was shown to
Mike Barth and Larry of Subsea Systems, both experts in underwater acoustics.
After some probing, noise coupling through the power supply was suspected to be
the likely cause. This can be fixed by running each receiver circuit from separate
voltage regulators and isolating the ground planes of each receiver. The ground
planes still need to be connected to one another but only at a single point to prevent
unwanted current loops. While these issues can be fixed, they will require a new
acoustic processor to be constructed.
The working distance of the acoustic system was tested in a limited manner
due to the problem in the receivers. With the inputs to two of the three receivers
grounded, it was discovered that the third receiver could be used with the pre and
post-amp gains set to their minimums. One transducer was connected to the
100
working receiver while another was connected to the output of the transponder
board. Both transducers were placed in a body of salt water with the face of each
transducer facing one another With the transponder board programmed to send out
a 1 millisecond pulse approximately 3 times per second, the receiving transducer
was moved further away until no signal was showing on the receiver’s LED. This
distance turned out to be approximately two (2) meters.
A few things can be done to improve the working distance of the BADNeS
proto-type. Amplifying the received signal more then the minimum amount will
help to increase the detection distance of the BADNeS. This can be done once the
noise-coupling issue between the receivers is solved. Increasing the voltage used to
drive the transducer will also increase the working distance. This can be
accomplished with the use of a properly designed transformer or a new transducer
driving circuit capable of higher voltages. The transducer could also be changed to
increase the working distance. A professionally designed and tested transducer
made specifically to suit this application would be ideal. These options should be
further pursued in future revisions of the BADNeS.
6.5 Overall System Performance
Since the overall performance of the BADNeS prototype couldn’t be
directly tested, the overall performance was estimated. The performance estimate
was calculated by summing up the expected positioning error of each error source.
101
The magnitude of the error sources were calculated if testing data was available, or
estimated in the case of sound velocity and sampling error. If test data was
available, the mean error and standard deviation of the measurements was added to
estimate an average maximum expected error. The error estimates were converted
into induced horizontal positioning errors using the plots in Section 2.3.2. Worst
case errors were assumed where the error depended on more than one factor. The
induced positioning errors from each error source were summed to produce the
overall system performance estimate. All the error estimates as well as the overall
system performance estimate are shown in Table 6.
102
Table 6 - Overall System Performance Estimate
Error
Source
Estimated
Horizontal
Position
Mean Standard
Error
Error
Error Deviation Estimate (meters)
GPS
3.92m
0.31m
4.23m
4.2
Sound
Velocity
10m/s
0
0.7m
0.7
Heading
-0.53°
0.13°
1.2°
2.4
X Tilt
0.05°
0.3°
0.85°
1.6
Y Tilt
0.00°
0.29°
0.79°
1.5
Total:
10.4
Notes
The error statistics of
the median
differential fix GPS
test were used.
Mean error is an
assumed value. The
estimated position
error was found using
Figure 10. Position
Error estimate based
on an assumed 0°
elevation bearing.
Error estimate
includes a 0.5°
sampling error.
Figure 12 was used to
find estimated
position error. Error
estimate based on an
assumed 0° elevation
bearing.
Error estimate
includes a 0.5°
sampling error.
Figure 11 was used to
find estimated
position error.
Error estimate
includes a 0.5°
sampling error.
Figure 11 was used to
find estimated
position error.
103
7 Conclusion
The goal of this project was to develop and test a low-cost underwater
positioning system suitable for recreational and scientific diving. It was desired
that the developed prototype unit cost less than $1,500, be easily transportable and
have a horizontal positioning accuracy of better than 10 meters. It is believed that
these goals have been met even though the first prototype, known as BADNeS, was
not fully functional. The prototype was constructed for approximately $800,
substantially less than current commercial systems which start at $15,000. The
prototype is also small in size allowing for easy transport on board small vessels.
Due to noise coupling in the receiver circuits, the prototype could not be directly
tested to determine its accuracy. Instead, each sensor that made up the prototype
was individually tested using survey grade equipment. Based on the test results, a
worst-case horizontal positioning error was estimated to be 10.4 meters based on a
GPS accuracy of 4.2 meters. On average the positions should be more accurate
than the worst case estimate making the desired 10 meter accuracy achievable.
In conclusion, the BADNeS prototype showed that an underwater
positioning system with all necessary components integrated is feasible for
personal use. The use of new board level sensor technology allowed for accurate
measurements at a fraction of the cost and size of commercially available sensors.
The cost of the prototype system was nearly 20 times cheaper than that of a
104
commercially available system. In addition, the developed prototype system could
be easily carried with one hand and fit in a circle of diameter just over a half meter.
Although this prototype was not fully functional, problems were identified and
their likely causes determined such that a future revision of the prototype will be
completely operational. Overall, the project was a success and the desired goals
were achieved.
105
References
"Acoustic Positioning Techniques." 2006. Sonardyne International Ltd. 11 Sept.
2006 <http://www.sonardyne.co.uk/Support/PositioningTechniques/index.html>.
Allegro MicroSystems Inc. A3950 DMOS Full-Bridge Motor Driver Datasheet.
2006. 27 Jan. 2008 <http://www.allegromicro.com/en/Products/Part_Numbers/
3950/3950.pdf>.
Analog Devices. ADIS16201 Programmable Dual-Axis Inclinometer /
Accelerometer Data Sheet. June 2006. 27 Jan. 2008
<http://www.analog.com/UploadedFiles/Data_Sheets/ADIS16201.pdf>.
APC International Ltd. Properties of APC Materials. 2006. 27 Jan. 2008
<http://www.americanpiezo.com/materials/apc_properties.html>.
Austin, T.C. “The Application of Spread Spectrum Signaling Techniques to
Underwater Acoustic Navigation,” Proceedings, A W ‘94, IEEE Conference on
Autonomous Underwater Vehicles, Cambridge MA, July, 1994.
CodaOctopus Products Ltd. CodaOctopus F180 Technical Brief. 11 Feb. 2008
<http://www.codaoctopus.com/motion/f180/techspec.asp>.
"Diver Hand-held GPS System." . 2006. Sound Ocean Systems, Inc.. 11 Sept. 2006
<http://www.soundocean.com/diverGPS-30.htm>.
"DLS-1 Diver Locator Sonar." . 2002. RJE International, Inc.. 11 Sept. 2006
<http://www.rjeint.com/pdf/DLS1.pdf>.
"EM-406 GPS Receiver Engine Board." 27 MAR 2006. GlobalSat Technology
Corp.. 15 Nov 2006
<http://www.usglobalsat.com/downloads/engineboards/EM406.pdf>.
Etek Navigation, Inc. Smart GPS Reciever Model: EB-85A. 10 Feb. 2008
<http://www.sparkfun.com/datasheets/GPS/EB-85A_Catalog.pdf>.
Frey, C.L.; Wood, S.L., "Development of an autonomous underwater vehicle for
sub-ice environmental monitoring in Prudhoe Bay, Alaska," OCEANS 2003.
Proceedings , vol.2, no., pp. 1161-1173 Vol.2, 22-26 Sept. 2003
106
"Gear Tests." . Mar. 2002. Divernet. 11 Sept. 2006
<http://www.divernet.com/equipment/0302divertests.htm>.
Gougeon Brothers, Inc. Typical Physical Properties. 25 Sept. 2007. 27 Jan. 2008
<http://www.westsystem.com/frames/tier2/productinfo/typicalphysical
properties.htm>.
Lekkerkerk, Huibert-Jan, et al. Handbook of Offshore Surveying:
Volume 1 (Preparation and Positioning). London: Oilfield Publications Limited,
2007.
Lekkerkerk, Huibert-Jan, et al. Handbook of Offshore Surveying:
Volume 2 (Acquisition & Processing). London: Oilfield Publications Limited,
2007.
Lurton, Xavier. An Introduction to Underwater Acoustics. Chichester: Praxis
Publishing, 2002.
Misra, Pratap, and Per Enge. Global Positioning System Signals, Measurements,
and Performance. Lincoln: Ganga-Jamuna Press, 2004.
National GeoSpatial-Intelligence Agency. Magnetic Total Intensity at 2005.0 from
the World Magnetic Model 2005. 3 Nov. 2005. 27 Jan. 2008
<http://www.ngdc.noaa.gov/seg/WMM/data/wmm-F05.pdf>.
"Navigation and Positioning ." AUV DesignInfo Page. 2001. International
Submarine Engineering Ltd.. 15 Nov 2006
<http://www.ise.bc.ca/WADEnavandpos.html>.
NDT Resource Center Characteristics of Piezoelectric Transducers. 27 Jan. 2008
<http://www.ndt-ed.org/EducationResources/CommunityCollege/Ultrasonics/
EquipmentTrans/characteristicspt.htm>.
Otter Products, LLC. OtterBox.Com Knowledge Base. 27 Jan. 2008
<http://www.otterbox.com/knowledge_base/questions/39/To+what+depth+are+
OtterBox+waterproof+to%3F>.
107
PNI Corporation. Application Note: Multipoint Calibration Primer. 13 Jan. 2004.
27 Jan. 2008 <https://www.pnicorp.com/downloadResource/c40c/manuals/53/
Ap+Note+Multipoint+Calibration+Primer+%28APNOTE+-+1001766++R01%29.pdf>.
PNI Corporation. MicroMag3 Data Sheet. PNICorp.com. June 2006. 27 Jan. 2008
<https://www.pnicorp.com/downloadResource/c40c/manuals/110/
MicroMag3+3-Axis+Sensor+Module_June+2006.pdf>.
S G Brown, ed. Meridian Surveyor System Manual. Issue 2.6 ed. 2003.
Sparkfun Electronics. Reflow Skillet. 2006. 27 Jan. 2008
<http://www.sparkfun.com/commerce/present.php?p=Reflow%20Skillet>.
"TrackLink Models." May 2005. LinkQuest Inc.. 01 Dec 2006
<http://www.link-quest.com/html/models2.htm>.
Waite, A. D. SONAR for Practising Engineers. 3rd ed. Chichester: John Wiley &
Sons Limited, 2002.
108
Appendix A: Circuit Diagrams
(Note: Larger printouts included in the envelope attached to the back cover.)
109
110
111
112
Appendix B: PCB Layout
113
Main Board – Top Layer
114
Main Board – Bottom Layer
115
Main Board – Silk Screen
116
Acoustic Processor – Top Layer
117
Acoustic Processor – Bottom Layer
118
Acoustic Processor – Silk Screen
119
Transponder – Top Layer
120
Transponder – Bottom Layer
121
Transponder – Silk Screen
122
Appendix C: PIC Assembly Code
123
;**********************************************************************************
;************************* MAIN BOARD MICROCONTROLLER CODE ************************
;**********************************************************************************
.equ __33FJ128GP306, 1
.include "p33FJ128GP306.inc"
;..............................................................................
;Configuration bits:
;..............................................................................
config __FOSC, FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_EC
;Turn off clock switching and
;fail-safe clock monitoring and
;use the External Clock as the
;system clock
config __FWDT, FWDTEN_OFF & WINDIS_OFF;Turn off Watchdog Timer
config __FPOR, FPWRT_PWR128
;Set Power on Timer 128 mSec
config __FOSCSEL, FNOSC_PRIPLL & IESO_OFF & TEMP_OFF
;Setup Oscillator (w/PLL)
config __FGS, GSS_OFF & GCP_OFF & GWRP_OFF ;Disable Code protect
config __FSS, RSS_NO_RAM & SSS_NO_FLASH & SWRP_WRPROTECT_OFF ;No security
config __FBS, RBS_NO_RAM & BSS_NO_FLASH & BWRP_WRPROTECT_OFF ;
;..............................................................................
;Program Specific Constants (literals used in code)
;..............................................................................
;----DATALOGGER
.equ
.equ
.equ
.equ
.equ
EQUATES--------------------------DL_PORT,PORTC
;
DL_TRIS,TRISC
;
DL_RST,1
;RESET LINE
DL_STOP,14
;STOP LINE
DL_ENABLE,13
;ENABLE LINE
;----GPS (UART 1) EQUATES------------------------.equ
GPS_PORT,PORTF
;
.equ
GPS_TRIS,TRISF
;
.equ
GPS_ENABLE,6
;
.equ
.equ
.equ
BAUD_NUM1,51
;Baud Rate Number (51=9600baud,103=4800)
;19200=25,38400=12
U1MODE_C,0b1000000000000000
;U1MODE Init Value - BRGH = 0
U1STA_C,0b0000000000000000
;U1STA Init Value
;----DATALOG,COMPUTER,BLUETOOTH (UART 2) EQUATES-.equ
BAUD_NUM2,12
;Baud Rate Number (51=9600baud,103=4800)
;19200=25,38400=12
.equ
U2MODE_C,0b1000000000000000
;U2MODE Init Value - BRGH = 0
.equ
U2STA_C,0b0000000000000000
;U2STA Init Value
;----MISC INTERRUPT EQUATES----------------------.equ
INT_PORT,PORTD
;
.equ
INT_TRIS,TRISD
;
.equ
GPS_INT,11
;GPS 1PPS OUTPUT
.equ
BT_PIO5,0
;BLUETOOTH AUX IO
.equ
BT_CONN,10
;BLUETOOTH CONNECTION ACTIVE
.equ
RTC_INT,9
;RTC INTERRUPT PIN
124
.equ
.equ
.equ
.equ
UI_AIO2,8
UI_AIO3,5
UI_PORT,PORTC
UI_AIO1,15
;USER INTERFACE AUX IO
;
;
;USER INTERFACE AUX IO
;----UART 2 SOURCE SELECT EQUATES----------------.equ
U2SS_PORT,PORTD
;
.equ
U2SS_TRIS,TRISD
;
.equ
RXSS0,1
;RECIEVE SOURCE SELECT 0
.equ
RXSS1,2
;RECIEVE SOURCE SELECT 1
.equ
TXSS0,3
;TRANSMIT SOURCE SELECT 0
.equ
TXSS1,4
;TRANSMIT SOURCE SELECT 1
;----USER INTERFACE EQUATES----------------------;----I2C EQUATES (RTC, UI)-----------------------.equ
I2C_PORT,PORTG
;
.equ
I2C_SCL,2
;
.equ
I2C_SDA,3
;
;----TILT SENSOR EQUATES-------------------------.equ
XL_PORT,PORTB
;
.equ
XL_TRIS,TRISB
;
.equ
XL_SCLK,12
;
.equ
XL_DOUT,13
;
.equ
XL_DIN,14
;
.equ
XL_CS,15
;
.equ
XL_DIO0,11
;
;----ACOUSTIC PROCESSOR EQUATES------------------.equ
AP_PORT,PORTG
;
.equ
AP_TRIS,TRISG
;
.equ
AP_SS,9
;
.equ
AP_SDO,7
;
.equ
AP_SCK,6
;
.equ
AP_SDI,8
;
.equ
AP_APORT,PORTC
;
.equ
AP_AIO1,2
;
;----AUX CONNECTION EQUATES----------------------.equ
AUX_PORT,PORTG
;
.equ
AUX_1,0
;
.equ
AUX_2,14
;
.equ
AUX_3,12
;
.equ
AUX_4,13
;
.equ
AUX_5,15
;
;----MAGNETOMETER SPI EQUATES--------------------.equ
MSSPORT,PORTB
;Magnetometer SS Port
.equ
MSSTRIS,TRISB
;Tris
.equ
MSSPIN,3
;pin
.equ
.equ
.equ
MRESPORT,PORTB
MRESTRIS,TRISB
MRESPIN,5
;Magnetometer Reset Port
;Tris
;pin
.equ
.equ
.equ
MDRDYPORT,PORTB
MDRDYTRIS,TRISB
MDRDYPIN,4
;Magnetometer DRDY Port
;Tris
;pin
.equ
.equ
.equ
MSCLKPORT,PORTB
MSCLKTRIS,TRISB
MSCLKPIN,0
;Magnetometer SCLK Port
;Tris
;pin
125
.equ
.equ
.equ
MMOSIPORT,PORTB
MMOSITRIS,TRISB
MMOSIPIN,2
;Magnetometer MOSI Port
;Tris
;pin
.equ
.equ
.equ
MMISOPORT,PORTB
MMISOTRIS,TRISB
MMISOPIN,1
;Magnetometer MISO Port
;Tris
;pin
;..............................................................................
;Global Declarations:
;..............................................................................
;
.global __reset
.global _main
;The label for the first line of code.
;required to invoke data initialization
.global
.global
.global
.global
.global
;Declare UART 2 Interrupt
;Declare UART 1 Interrupt
;
;
;
__U2RXInterrupt
__U1RXInterrupt
__SPI2Interrupt
__SPI2ErrInterrupt
__INT4Interrupt
;.global __T1Interrupt
;Declare Timer 1 ISR name global
;..............................................................................
;Constants stored in Program space
;..............................................................................
;
.section .myconstbuffer, code
;
.palign 2
;Align next word stored in Program space to an
;
;address that is a multiple of 2
;ps_coeff:
;
.hword
0x0002, 0x0003, 0x0005, 0x000A
;..............................................................................
;Uninitialized variables in X-space in data memory
;..............................................................................
.section .xbss, bss, xmemory
GPSMSG1: .space 80
;First GPS Message Buffer
GPSMSG2: .space 80
;Second GPS Message Buffer
GPSBUF1CNT: .space
2
;Buffer 1 Byte Count
GPSBUF2CNT: .space
2
;Buffer 2 Byte Count
GPSFLAGS: .space 2
;GPS Flags
;bit 0: 1 = Message in progress , 0 = Message not in progress
;bit 1: 1 = Buffer Full Error , 0 = No Buffer Full Error
;bit 2: 1 = buffer 1 is full , 0 = buffer 1 is available
;bit 3: 1 = buffer 1 requires writing , 0 = buffer 1 does not require writing
;bit 4: 1 = buffer 2 is full , 0 = buffer 2 is available
;bit 5: 1 = buffer 2 requires writing , 0 = buffer 2 does not require writing
;bit 6: 1 = using buffer 1, 0 = using buffer 2
;bit 7:
1 = GPS Data Written, 0 = No GPS Data Written
U1RECEIVE: .space 2
;received byte storage
XMAG:
.space 2
;X-axis magnetometer measurement
YMAG:
.space 2
;Y-axis magnetometer measurement
ZMAG:
.space 2
;Z-axis magnetometer measurement
TEMP:
.space 2
;
XTilt: .space 2
;
YTilt: .space 2
;
XAccel: .space 2
;
YAccel: .space 2
;t
SPIRNUM:
.space 2
;Number of Bytes Received via SPI
SPITNUM:
.space 2
;Number of Bytes to transmit via SPI
126
SPIFLAGS:
.space 2
;SPI Flags
SPITRANSMIT:
.space 30
;SPI Transmit Buffer
SPIRECEIVE: .space 20
;SPI Receive Buffer
AP_COMMAND: .space 2
;
AP_RANGEH: .space 2
;
AP_RANGEL: .space 2
;
AP_TRANS1: .space 2
;
AP_TRANS2: .space 2
;
AP_TRANS3: .space 2
;
AP_TRANSORDER: .space 2
;
AP_TPNC:
.space 2
;default #45 (1ms)
AP_PRE1:
.space 2
;default 0x007F
AP_PRE2:
.space 2
;default 0x007F
AP_PRE3:
.space 2
;default 0x007F
AP_POST1:
.space 2
;default 0x007F
AP_POST2:
.space 2
;default 0x007F
AP_POST3:
.space 2
;default 0x007F
AP_BIGTOH: .space 2
;default 0x0131
AP_BIGTOL: .space 2
;default 0x2D00
AP_SMALLTOH:
.space 2
;default 0x0000
AP_SMALLTOL:
.space 2
;default 0x4E20
MAIN_FLAGS:
.space 2
;bit 0: 1 = 1PPS Has Occurred 0 = 1PPS Hasn't Occurred Yet
;bit 1: 1 = Debug Mode, 0 = Not Debug Mode
;bit 2: 1 = Debug Mode (Don't Wait for PPS), 0 = Wait for PPS
;bit 3: 1 = Record Data, 0 = Don't Record Data
;bit 4: 1 = Send Data out to Computer on Store, 0 = Don't send data out
;bit 5: 1 = Echo RS232 Characters, 0 = Don't Echo
;bit 6: 1 = GPS COM MODE, 0 = Not GPS COM MODE
;bit 7: 1 = Read Incoming GPS Data, 0 = Do NOT read incoming gps data
;bit 8: 1 = Datalog COM Mode, 0 = Not Datalog COM Mode
;bit 9: 1 = Bluetooth Connected, 0 = Bluetooth Not Connected
AP_STIMEH: .space 2
;
AP_STIMEL: .space 2
;
AP_ETIMEH: .space 2
;
AP_ETIMEL: .space 2
;
TILT_TIMEH: .space 2
;
TILT_TIMEL: .space 2
;
MAG_TIMEH: .space 2
;
MAG_TIMEL: .space 2
;
MAG_CSV:
TILT_CSV:
AP_CSV:
TIME_CSV:
UI2NUMT:
.space
.space
.space
.space
30
40
40
50
.space 10
U2RECEIVE: .space 30
U2RNUM:
.space 2
U2FLAGS:
.space 2
;
;
;
;
;
;UART 2 Received words
;UART 2 Received Number of words
;UART 2 FLAGS
;bit 0 - Interrupt Occured Flag? 1= No, 0= Yes
;bit 1: 1 = Last data sent to datalogger, 0 = Last
;data sent to computer
TESTH:
.space 2
TESTL:
.space 2
;..............................................................................
;Uninitialized variables in Y-space in data memory
;..............................................................................
;
;y_input:
.section .ybss, bss, ymemory
.space 2*SAMPLES
127
;..............................................................................
;Initialized variables in data memory
;..............................................................................
;----Debug Display Constants-----------------------------.section .data
DEBUG_MAG: .asciz "MAG X
Y
Z "
DEBUG_MAGT: .asciz "
MAGTIME: "
DEBUG_TILT: .ascii "TILT X
Y
"
DEBUG_TILTT: .ascii " TILTTIME: "
DEBUG_A1: .ascii "AP - RANGE: "
DEBUG_A2: .ascii "
ORDER: "
DEBUG_A3: .ascii "
TRAN1: "
DEBUG_A4: .ascii "
TRAN2: "
DEBUG_A5: .ascii "
TRAN3: "
DEBUG_A6: .ascii "
STIME: "
DEBUG_A7: .ascii "
ETIME: "
DEBUG_CMD: .ascii "'q' - Exit Debug Mode 's' - Setup Parameters 'g' - GPS COM Mode
'l' - Loopback Mode 'o' - Datalog Mode 'm' - OS DL "
MAIN_CMD: .ascii "'r' - RECORDPAUSE 's' - STARTSTOP Debug Out 'd' - Debug Mode "
UI2NUMR:
.ascii "Please Enter a 00 digit number. "
UI2NUMERR: .ascii "Number is too large, try again"
VALDISP1: .ascii "1 AP_PRE1: XXX
[MAX: 127]"
VALDISP2: .ascii "2 AP_PRE2: XXX
[MAX: 127]"
VALDISP3: .ascii "3 AP_PRE3: XXX
[MAX: 127]"
VALDISP4: .ascii "4 AP_POST1: XXX
[MAX: 127]"
VALDISP5: .ascii "5 AP_POST2: XXX
[MAX: 127]"
VALDISP6: .ascii "6 AP_POST3: XXX
[MAX: 127]"
VALDISP7: .ascii "7 AP_TPNC: XXXXX
[65535]"
VALDISP8: .ascii "8 AP_BIGTO: XXXXXXXXXX [MAX]"
VALDISP9: .ascii "9 AP_SMLTO: XXXXXXXXXX[FFFF]"
DISPVAL_INS: .ascii "'q' - Exit (1-9) - Change Parameter "
GPSBUFFULL: .ascii "ERROR: GPS BUFFER FULL"
GPSDATAERR: .ascii "ERROR: GPS RX DATA"
GPSPPS:
.ascii "[PPS]"
U1ORERR:
.ascii "ERROR: U1OR "
U1FRERR:
.ascii "ERROR: U1FE "
U2ORERR:
.ascii "ERROR: U2OR "
U2FRERR:
.ascii "ERROR: U2FE "
;GPSSETRATE: .ascii "$PSRF103,00,00,01,01*25",<0xd>,<0xa>
;
;..............................................................................
;Uninitialized variables in Near data memory (Lower 8Kb of RAM)
;..............................................................................
;
.section .nbss, bss, near
.section vars,bss,address(0x900)
;..............................................................................
;Code Section in Program Memory
;..............................................................................
.text
;Start of Code section
__reset:
MOV
#__SP_init, W15
;Initalize the Stack Pointer
MOV
#__SPLIM_init, W0
;Initialize the Stack Pointer Limit Register
MOV
W0, SPLIM
;
NOP
;Add NOP to follow SPLIM initialization
_main:
;Initialize PLL to proper frequency
;PLL will work on startup if 4mHz<Fin<8mHz
;(it was checked that PLL settings will within
;limits during this PLL update process)
mov
#0x00C0,W0
;PLLPRE=2,PLLPOST=8 (IC = 8mhz)
mov
W0,CLKDIV
;
128
mov
mov
#0x003E,W0
W0,PLLFBD
;Set PLL Multiplier=64 (IC = 8mhz)
;
;Disable all modules
mov
#0xFFFF,W0
mov
W0,PMD1
mov
W0,PMD2
mov
W0,PMD3
;
;
;
;
;Disable all open-drains
mov
#0x0000,W0
mov
W0,ODCD
mov
W0,ODCF
mov
W0,ODCG
;
;Port D
;Port F
;Port G
;Disable Analog Function of I/O Pins
mov
#0xFFFF,W0
;
mov
W0,AD1PCFGH
;
mov
W0,AD1PCFGL
;
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
main_init
bt_receive_check
bt_transmit_check
UART1_Init
UART2_Init
gps_init
gps_enable
data_init
data_enable
AP_INIT
SPI_INIT
Magnetometer_Init
Tilt_init
Tilt_Setup
Timer23_init
OnePPS_init
;Initialize UART2 Select pins
;Selects Bluetooth / Computer Reception
;Selects Bluetooth / Computer Transmission
;Initialize GPS
;Initialize RS232 / Bluetooth
;Initialize GPS Enable pins
;Enable GPS
;Initialize Datalogger Pins
;Enable Data Logger
;
;
;Initialize Magnetometer
;Initialize Tilt Sensor
;Setup the tilt sensor
;Initialize 32-bit timer
;Initialize 1PPS Functionality
clr
clr
clr
clr
clr
clr
clr
mov
mov
mov
mov
mov
mov
mov
mov
clr
clr
clr
clr
clr
clr
clr
TEMP
MAIN_FLAGS
AP_RANGEH
AP_RANGEL
AP_TRANS1
AP_TRANS2
AP_TRANS3
#0x0001,W0
W0,AP_STIMEH
#0x0001,W0
W0,AP_STIMEL
#0x0001,W0
W0,AP_ETIMEH
#0x0001,W0
W0,AP_ETIMEL
TILT_TIMEH
TILT_TIMEL
MAG_TIMEH
MAG_TIMEL
U2FLAGS
U2RNUM
GPSFLAGS
;Used for GPS/Magnetometer Flag
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
call
call
delay100ms
delay100ms
;
;
129
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
delay100ms
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;******************************************************************************
;******************************************************************************
main_loop:
;Ensure bluetooth data can come through
call
bt_receive
;Selects Bluetooth Reception
call
bt_conn_check
;Check if Bluetooth Connection Is Active, set flag
;accordingly
;Computer Mode or Datalog Mode?
btsc
MAIN_FLAGS,#9
goto
main_comloop
;Check if bluetooth connection is active
;yes, connection is active, computer mode
;no active bluetooth connection, Datalog Mode
;:DATALOG MODE:DATALOG MODE:DATALOG MODE:DATALOG MODE:DATALOG MODE:DATALOG MODE:
;Datalog Mode
call
data_enable
;enable datalogger
call
data_settx
;Select datalogger as TX device
;
;Collect Readings?
btss
MAIN_FLAGS,#0
;Wait for 1PPS Pulse (Indicates GPS Fix)
goto
main_loop
;No 1PPS yet, loop again
;1PPS has occurred, Get sensor data
bset
MAIN_FLAGS,#7
;Read Incoming GPS data
call
FIND_POSITION
;Get Sensor Data
;Store Readings
call
sensor_data_write
;record Sensor
call
delay100ms
;
call
delay100ms
;
call
gps_data_write
;record GPS data
mov
call
mov
call
#0x000D,W0
U2_Transmit
#0x000A,W0
U2_Transmit
;<cr> <lf>
;
;
;
bclr
MAIN_FLAGS,#0
;Reset 1PPS Flag-Wait for another GPS Reading
goto
main_loop
;
;:DATALOG MODE:DATALOG MODE:DATALOG MODE:DATALOG MODE:DATALOG MODE:DATALOG MODE:
;:COMPUTER MODE:COMPUTER MODE:COMPUTER MODE:COMPUTER MODE:COMPUTER MODE:COMPUTER
main_comloop:
call
data_stop
;Stop Data Logger
call
delay1s
;delay
call
data_disable
;Disable Data Logger
call
bt_settx
;Select bluetooth as TX device
130
call
mode_check
btsc
goto
MAIN_FLAGS,#2
main_debug
;Collect Readings?
btss
MAIN_FLAGS,#0
goto
main_loop
bset
MAIN_FLAGS,#7
call
FIND_POSITION
;Store Readings
call
sensor_data_write
call
delay100ms
call
delay100ms
call
gps_data_write
mov
call
mov
call
nop
bclr
goto
;:COMPUTER
;Check
;Debug
;Check
;enter
for change of modes
Mode?
for debug mode
debug mode
;Wait for 1PPS Pulse (Indicates GPS Fix)
;No 1PPS yet, loop again
;1PPS has occurred, Get sensor data
;Read Incoming GPS data
;Get Sensor Data
;record Sensor
;
;
;record GPS data
#0x000D,W0
U2_Transmit
#0x000A,W0
U2_Transmit
;<cr> <lf>
;
;
;
;store other data
MAIN_FLAGS,#0
;Reset 1PPS Flag - Wait for another GPS Reading
main_loop
;
MODE:COMPUTER MODE:COMPUTER MODE:COMPUTER MODE:COMPUTER MODE:COMPUTER
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
main_sdo:
call
HOME_DISPLAY
;Reset Cursor Position
call
ODEBUG_DISPLAY
;Display Orientation Data
call
ADEBUG_DISPLAY
;Display Acoustic Data
call
OT_DISPLAY
;Display Orientation Time
return
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
mode_check:
cp0
U2RNUM
;Check if any commands received
bra
NZ,mode_check_cmd
;
return
;no, command, return
mode_check_cmd:
clr
U2RNUM
;Clear receive byte count
mov
cp.b
bra
#0X0064,W0
U2RECEIVE
Z,mode_check_dbg
;'d' - Debug
;
;Debug Command Received
mov
cp.b
bra
#0X0072,W0
U2RECEIVE
Z,mode_check_rec
;'r' - record
;
;record Command Received
mov
cp.b
bra
#0X0073,W0
U2RECEIVE
Z,mode_check_sd
;'s' - Send out debug data
;
;Send out Debug Data Command Received
;Invalid Command, send out instructions
MAIN_CMD_SO:
call
CLEAR_DISPLAY
;
mov
mov
#MAIN_CMD,W2
#6,W1
;Send out Instruction line
;"'r' - "
131
call
STRING_DISPLAY
;
btsc
MAIN_FLAGS,#3
;RECORDING?
mov
#MAIN_CMD+#12,W2
;yes, display "PAUSE " instead of "RECORD"
mov
#6,W1
;
call
STRING_DISPLAY
;
mov
#MAIN_CMD+#17,W2
;" 's' - "
mov
#7,W1
;
call
STRING_DISPLAY
;
btsc
MAIN_FLAGS,#1
;Sending Data out?
mov
#MAIN_CMD+#29,W2
;yes, display "STOP " instead of "START"
mov
#5,W1
;
call
STRING_DISPLAY
;
mov
#MAIN_CMD+#33,W2
;" Data Out 'd' - Debug Mode"
mov
#27,W1
;
call
STRING_DISPLAY
;
mov
#0x0001,W1
;New line
call
NEWLINE_DISPLAY
;
return
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
mode_check_dbg:
bset
MAIN_FLAGS,#2
;set debug mode flag
return
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
mode_check_rec:
btg
MAIN_FLAGS,#3
;set record mode flag
call
MAIN_CMD_SO
;update display
return
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
mode_check_sd:
btg
MAIN_FLAGS,#1
;set send data mode flag
call
MAIN_CMD_SO
;update display
return
;
;******************************************************************************
;******************************************************************************
main_debug:
call
CLEAR_DISPLAY
;
bclr
MAIN_FLAGS,#7
;Don't store GPS data
bclr
IEC0,#U1RXIE
;Clear U1 Recieve Interrupt
bclr
MAIN_FLAGS,#1
;Turn off [PPS] Message Output
main_debugloop:
call
bt_receive_check
;Selects Bluetooth / Computer Reception
call
FIND_POSITION
;Get Sensor Data
call
call
call
call
HOME_DISPLAY
ODEBUG_DISPLAY
ADEBUG_DISPLAY
OT_DISPLAY
;Reset Cursor Position
;Display Orientation Data
;Display Acoustic Data
;Display Orientation Time
mov
call
#0x0002,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_CMD,W2
#114,W1
STRING_DISPLAY
;Send out Instruction line
;
;
cp0
bra
U2RNUM
NZ,debug_command
;Check if any commands received
;
132
goto
main_debugloop
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
debug_command:
clr
U2RNUM
;Clear receive byte count
mov
cp.b
bra
#0X0071,W0
U2RECEIVE
Z,cmdquitdebug
;'q' - Quit
;
;Quit Command Received
mov
cp.b
bra
#'s',W0
U2RECEIVE
Z,cmddispval
;'s' - display setup values for editing
;
;Display Values Command
mov
cp.b
bra
#'g',W0
U2RECEIVE
Z,cmdgpscom
;'g' - Enter GPS communication mode
;(can only exit by restarting microcontroller)
;GPS COM Mode Command
mov
cp.b
bra
#'l',W0
U2RECEIVE
Z,cmdlpbcom
;'l' - Enter Loopback Mode
;(can only exit by restarting microcontroller)
;Loopback COM Mode Command
mov
cp.b
bra
#'o',W0
U2RECEIVE
Z,cmddlcom
;'o' - Enter Datalog Mode
;(can only exit by restarting microcontroller)
;Datalog Mode Command
mov
cp.b
bra
#'m',W0
U2RECEIVE
Z,cmdosdlcom
;'m' - Enter Orientation Sensor Datalog Mode
;
;Orientation Sensor Datalog Mode Command
goto
main_debug
;Not a valid command
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmdosdlcom:
bclr
MAIN_FLAGS,#5
;Turn off character echo
call
data_enable
;enable datalogger
call
delay1s
;Allow time for the datalogger to turn on
cmdosdlcom_loop:
call
delay100ms
;Delay to lower sample rate
call
delay100ms
;to approximately 3 Hz
;Get Time
call
Timer23_read
;Time Stamp
mov
W1,MAG_TIMEH
;
mov
W0,MAG_TIMEL
;
;
call
Mag_Read_XYZ
;Read Heading Information
call
Tilt_Read
;Read Tilt Information
call
Tilt_Data_Mask
;
call
MAG_DF
;Store magnetometer CSV data
call
TILT_DF
;Store Tilt CSV data
call
TIME_DF
;Store Time CSV data
call
data_settx
;Select datalogger as TX device
;Send out Orientation Sensor Data
mov
#0x0024,W0
;'$ORSEN'
call
U2_Transmit
;
mov
#0x004F,W0
;
call
U2_Transmit
;
mov
#0x0052,W0
;
call
U2_Transmit
;
mov
#0x0053,W0
;
call
U2_Transmit
;
133
mov
call
mov
call
#0x0045,W0
U2_Transmit
#0x004E,W0
U2_Transmit
;
;
;
;
mov
call
mov
call
#0x002C,W0
U2_Transmit
#0x0020,W0
U2_Transmit
;', ' (Comma,Space)
;
;
;
mov
mov
call
#TIME_CSV+#36,W2
#0x000A,W1
STRING_DISPLAY
;Send out Time Stamp
;
;
mov
call
mov
call
#0x002C,W0
U2_Transmit
#0x0020,W0
U2_Transmit
;', ' (Comma,Space)
;
;
;
mov
mov
call
#MAG_CSV,W2
#22,W1
STRING_DISPLAY
;Send out Mag Data
;
;
mov
call
mov
call
#0x002C,W0
U2_Transmit
#0x0020,W0
U2_Transmit
;', ' (Comma,Space)
;
;
;
mov
mov
call
#TILT_CSV,W2
#14,W1
STRING_DISPLAY
;Send out Tilt Data
;
;
mov
call
mov
call
#0x000D,W0
U2_Transmit
#0x000A,W0
U2_Transmit
;CR, LF
;
;
;
;Done sending out data
cp0
U2RNUM
bra
NZ,cmdosdlcom_exit
goto
cmdosdlcom_loop
;Check if any key has been pressed
;yes, exit this loop.. but first save data
;no, repeat procedure
cmdosdlcom_exit:
clr
U2RNUM
;clear recieved byte
call
delay100ms
;
call
data_stop
;Stop Data Logger
call
delay1s
;delay
call
data_disable
;Disable Data Logger
call
bt_settx
;Select bluetooth as TX device
goto
main_debug
;Go back to debug mode
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmdgpscom:
bclr
MAIN_FLAGS,#5
;Turn off character echo
nop
;
bset
MAIN_FLAGS,#6
;Turn on GPS COM MODE
clr
U2RNUM
;
bset
IEC0,#U1RXIE
;Turn On U1 Recieve Interrupt
goto
cmdgpscom
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmdlpbcom:
bset
MAIN_FLAGS,#5
;Turn on character echo
clr
U2RNUM
;
134
goto
cmdlpbcom
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddlcom:
bclr
MAIN_FLAGS,#5
;Turn off character echo
call
data_enable
;enable datalogger
call
delay1s
;Allow datalogger time to turn on
bset
MAIN_FLAGS,#8
;Turn on datalog mode
clr
U2RNUM
;
goto
cmddlcom
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddispval:
clr
U2RNUM
;clear received bytes count
call
CLEAR_DISPLAY
;
call
VAL_DISPLAY
;Display values
mov
call
#0x0002,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DISPVAL_INS,W2
#36,W1
STRING_DISPLAY
;Send out Instruction line
;
;
bset
MAIN_FLAGS,#5
cmddispval_wait:
cp0
U2RNUM
bra
Z,cmddispval_wait
;Echo Characters
clr
U2RNUM
;Check if any commands received
;
;New byte received
;Clear receive byte count
mov
cp.b
bra
#'q',W0
U2RECEIVE
Z,cmddisp_quit
;'q' - Quit
;
;Quit Command Received, back to debug
mov
cp.b
bra
#'1',W0
U2RECEIVE
Z,cmddisp_op1
;'1' - AP_PRE1
;
;Option 1 Selected
mov
cp.b
bra
#'2',W0
U2RECEIVE
Z,cmddisp_op2
;'2' - AP_PRE2
;
;Option 2 Selected
mov
cp.b
bra
#'3',W0
U2RECEIVE
Z,cmddisp_op3
;'3' - AP_PRE3
;
;Option 3 Selected
mov
cp.b
bra
#'4',W0
U2RECEIVE
Z,cmddisp_op4
;'4' - AP_POST1
;
;Option 4 Selected
mov
cp.b
bra
#'5',W0
U2RECEIVE
Z,cmddisp_op5
;'5' - AP_POST2
;
;Option 5 Selected
mov
cp.b
bra
#'6',W0
U2RECEIVE
Z,cmddisp_op6
;'6' - AP_POST3
;
;Option 6 Selected
mov
cp.b
bra
#'7',W0
U2RECEIVE
Z,cmddisp_op7
;'7' - AP_TPNC
;
;Option 7 Selected
mov
cp.b
#'8',W0
U2RECEIVE
;'8' - AP_BIGTO
;
135
bra
Z,cmddisp_op8
;Option 8 Selected
mov
cp.b
bra
#'9',W0
U2RECEIVE
Z,cmddisp_op9
;'9' - AP_SMALLTO
;
;Option 9 Selected
mov
cp.b
bra
#'g',W0
U2RECEIVE
Z,cmddisp_opg
;'g' ;
;
goto
cmddispval
;No valid command received, wait some more
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_quit:
;
call
AP_SP
;Send out acoustic board parameters
call
delay100ms
;give slight delay for acoustic processor
goto
main_debug
;return to debug menu
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_opg:
call
AP_SP
; 'g' Save parameters to Acoustic Board
goto
cmddispval
;
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op1:
mov
#3,W0
;3-Digits requested
mov
#0,W2
;Max Allowable Value (MSW)
mov
#127,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_PRE1
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op2:
mov
#3,W0
;3-Digits requested
mov
#0,W2
;Max Allowable Value (MSW)
mov
#127,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_PRE2
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op3:
mov
#3,W0
;3-Digits requested
mov
#0,W2
;Max Allowable Value (MSW)
mov
#127,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_PRE3
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op4:
mov
#3,W0
;3-Digits requested
mov
#0,W2
;Max Allowable Value (MSW)
mov
#127,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_POST1
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op5:
mov
#3,W0
;3-Digits requested
mov
#0,W2
;Max Allowable Value (MSW)
mov
#127,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_POST2
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op6:
mov
#3,W0
;3-Digits requested
136
mov
#0,W2
;Max Allowable Value (MSW)
mov
#127,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_POST3
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op7:
mov
#5,W0
;5-Digits requested
mov
#0,W2
;Max Allowable Value (MSW)
mov
#0xFFFF,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_TPNC
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op8:
mov
#10,W0
;10-Digits requested
mov
#0xFFFF,W2
;Max Allowable Value (MSW)
mov
#0xFFFF,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_BIGTOL
;store new value
mov
W1,AP_BIGTOH
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmddisp_op9:
mov
#10,W0
;10-Digits requested
mov
#0xFFFF,W2
;Max Allowable Value (MSW)
mov
#0xFFFF,W1
;Max Allowable Value (LSW)
call
UI2NUM
;Collect new user value
mov
W0,AP_SMALLTOL
;store new value
mov
W1,AP_SMALLTOH
;store new value
goto
cmddispval
;display new value
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cmdquitdebug:
bclr
MAIN_FLAGS,#2
;clear debug mode flag
bclr
MAIN_FLAGS,#5
;Turn off character echo
bset
IEC0,#U1RXIE
;Turn On U1 Recieve Interrupt
call
MAIN_CMD_SO
;Send out Main CMD
goto
main_loop
;
;******************************************************************************
;******************************************************************************
;*********************************************************
;FIND_POSITION Find Position Routine
;
;Requests reading from acoustic processor, reads all
;orientation sensors, formats orientation and acoustic
;processor readings as CSVs in data memory. All data
;is time stamped with a count since the last 1PPS. Clears
;1PPS flag before returning.
;*********************************************************
FIND_POSITION:
call
mov
mov
call
Timer23_read
W1,AP_STIMEH
W0,AP_STIMEL
AP_GM
;Time Stamp
;
;
;Request Range and Bearing from AP Board
call
mov
mov
call
Timer23_read
W1,MAG_TIMEH
W0,MAG_TIMEL
Mag_Read_XYZ
;Time Stamp
;
;
;Read Heading Information
call
Timer23_read
;Time Stamp
137
mov
mov
call
call
call
call
W1,TILT_TIMEH
W0,TILT_TIMEL
Tilt_Read
Tilt_Data_Mask
MAG_DF
TILT_DF
;
;
;Read Tilt Information
;
;Store magnetometer CSV data
;Store Tilt CSV data
call
call
mov
mov
AP_GM_READ
Timer23_read
W1,AP_ETIMEH
W0,AP_ETIMEL
;Wait for then collect AP Measurements
;Time Stamp
;
;
call
AP_DF
;Store AP CSV data
call
TIME_DF
;Store Time CSV data
return
;
;*********************************************************
;*********************************************************
;UI2NUM User Input to Number
;
;Given the number of digits to request and a maximum
;allowable value this function will prompt the user for
;input and then convert the ASCII BCD to a binary number.
;Inputs: W0 - Number of digits to request
;
W1 - Maximum allowable value (LSW)
;
W2 - Maximum allowable value (MSW)
;Output: W0 - binary number (16-bit Word, LSW if 32-bit)
;
W1 - binary number (MSW if 32-bit)
;*********************************************************
UI2NUM:
;Make request for proper number of digits
push
W1
;Save inputs
push
W2
;
push
W0
;
clr
U2RNUM
;clear received byte counter
call
num2ascii
;Convert # of digits to ASCII
mov
#UI2NUMR+#15,W3
;Prepare output phrase
mov.b W2,[W3++]
;Place tens digit
mov.b W1,[W3++]
;Place Ones digit
mov
call
#0x0002,W1
NEWLINE_DISPLAY
;2 New lines
;
mov
mov
call
mov
call
#UI2NUMR,W2
#31,W1
STRING_DISPLAY
#0x0002,W1
NEWLINE_DISPLAY
;Send out request to user
;
;
;2 New lines
;
pop
push
W0
W0
;Restore number of digits
;save number of digits once again
bset
MAIN_FLAGS,#5
UI2NUM_wait:
cp
U2RNUM
bra
LTU,UI2NUM_wait
;Echo Characters to User
;Wait for requested number of digits
;
;not enough bytes yet, wait
bclr
MAIN_FLAGS,#5
;Stop Echoing Characters to User
mov
sub
#10,W2
W2,W0,W2
;10 = Max number of digits
;10 - number of digits => W2
;Fill UI2NUMT with 10 digit string (fill in missing digits with 0x00)
138
mov
#UI2NUMT,W3
UI2NUM_FC:
cp0
W2
bra
NZ,UI2NUM_SF
;
pop
W2
push
W2
mov
#U2RECEIVE,W4
UI2NUM_DC:
cp0
W2
bra
NZ,UI2NUM_DF
;restore number of digits
;
;
;Fill digits in array
;Check if there are still digits
;yes, fill one
;Check if there are still missing digits
;yes, fill one
clr
U2RNUM
;
bclr
SR,#15
;Clear OA bit
;Should now have a string of 10 BCD digits in UI2NUMT
mov
#UI2NUMT,W3
;
clr
A
;Clear accumulator
;Billions digit
mov
#0x3B9A,W0
;(1,000,000,000 in hex)
mov
W0,ACCBH
;
mov
#0xCA00,W0
;
mov
W0,ACCBL
;
mov.b [W3++],W0
;
UI2NUM_BDT:
;
cp0.b W0
;Check for Billions
bra
Z,UI2NUM_HMD
;no,billions, check hundred millions
add
A
;add one billion
dec.b W0,W0
;
bra
UI2NUM_BDT
;
UI2NUM_HMD:
mov
#0x05F5,W0
mov
W0,ACCBH
mov
#0xE100,W0
mov
W0,ACCBL
mov.b [W3++],W0
UI2NUM_HMT:
cp0.b W0
bra
Z,UI2NUM_TMD
add
A
dec.b W0,W0
bra
UI2NUM_HMT
;Hundred Millions Digit
;(100,000,000 in hex)
;
;
;
;
;
;Check for Billions
;no hundred millions, check ten millions
;add one hundred million
;
;
UI2NUM_TMD:
mov
#0x0098,W0
mov
W0,ACCBH
mov
#0x9680,W0
mov
W0,ACCBL
mov.b [W3++],W0
UI2NUM_TMT:
cp0.b W0
bra
Z,UI2NUM_MD
add
A
dec.b W0,W0
bra
UI2NUM_TMT
;Ten Millions Digit
;(10,000,000 in hex)
;
;
;
;
;
;Check for Ten Millions
;no ten millions, check millions
;add one ten million
;
;
UI2NUM_MD:
mov
#0x000F,W0
mov
W0,ACCBH
mov
#0x4240,W0
mov
W0,ACCBL
mov.b [W3++],W0
UI2NUM_MT:
;Millions Digit
;(1,000,000 in hex)
;
;
;
;
;
139
cp0.b
bra
add
dec.b
bra
W0
Z,UI2NUM_HTD
A
W0,W0
UI2NUM_MT
;Check for Millions
;no millions, check hundred thousands
;add one million
;
;
UI2NUM_HTD:
mov
#0x0001,W0
mov
W0,ACCBH
mov
#0x86A0,W0
mov
W0,ACCBL
mov.b [W3++],W0
UI2NUM_HTT:
cp0.b W0
bra
Z,UI2NUM_TTD
add
A
dec.b W0,W0
bra
UI2NUM_HTT
;Hundred Thousands Digit
;(100,000 in hex)
;
;
;
;
;
;Check for Hundred Thousands
;no hundred thousands, check tens of thousands
;add one hundred thousand
;
;
UI2NUM_TTD:
mov
#0x0000,W0
mov
W0,ACCBH
mov
#0x2710,W0
mov
W0,ACCBL
mov.b [W3++],W0
UI2NUM_TTT:
cp0.b W0
bra
Z,UI2NUM_TD
add
A
dec.b W0,W0
bra
UI2NUM_TTT
;Ten Thousands Digit
;(10,000 in hex)
;
;
;
;
;
;Check for ten Thousands
;no ten thousands, check thousands
;add ten thousand
;
;
UI2NUM_TD:
mov
mov
mov
mov
mov.b
UI2NUM_TT:
cp0.b
bra
add
dec.b
bra
;Thousands Digit
;(1,000 in hex)
;
;
;
;
;
;Check for Thousands
;no thousands, check hundreds
;add thousand
;
;
UI2NUM_HD:
mov
mov
mov
mov
mov.b
UI2NUM_HT:
cp0.b
bra
add
dec.b
bra
#0x0000,W0
W0,ACCBH
#0x03E8,W0
W0,ACCBL
[W3++],W0
W0
Z,UI2NUM_HD
A
W0,W0
UI2NUM_TT
#0x0000,W0
W0,ACCBH
#0x0064,W0
W0,ACCBL
[W3++],W0
W0
Z,UI2NUM_TEND
A
W0,W0
UI2NUM_HT
UI2NUM_TEND:
mov
#0x0000,W0
mov
W0,ACCBH
mov
#0x00A,W0
mov
W0,ACCBL
;Hundreds Digit
;(100 in hex)
;
;
;
;
;
;Check for hundreds
;no hundreds, check tens
;add hundred
;
;
;Tens Digit
;(10 in hex)
;
;
;
140
mov.b [W3++],W0
UI2NUM_TENT:
cp0.b W0
bra
Z,UI2NUM_OD
add
A
dec.b W0,W0
bra
UI2NUM_TENT
;
;
;Check for tens
;no tens, check ones
;add ten
;
;
UI2NUM_OD:
mov
mov
mov
mov
mov.b
UI2NUM_OT:
cp0.b
bra
add
dec.b
bra
;Ones Digit
;(1 in hex)
;
;
;
;
;
;Check for ones
;no ones, check number
;add one
;
;
#0x0000,W0
W0,ACCBH
#0x0001,W0
W0,ACCBL
[W3++],W0
W0
Z,UI2NUM_CHECK
A
W0,W0
UI2NUM_OT
UI2NUM_CHECK:
pop
W0
pop
W3
pop
W2
push
W2
push
W3
push
W0
;Check that number is under max
;num digits
;restore max allowable value (MSW)
;(LSW)
;re-save everything
;in case of error
;
;Check for ACC A overflow
bra
OA,UI2NUM_ERR
;overflow occurred... number too large
mov
mov
ACCAH,W1
ACCAL,W0
;UI Number (MSW)
;UI Number (LSW)
cp
bra
W1,W3
GEU,UI2NUM_CHK2
;UIH < MAXH?
;no, keep checking
UI2NUM_FIN:
pop
W3
pop
W3
pop
W3
return
UI2NUM_CHK2:
cpseq W1,W3
bra
UI2NUM_ERR
cp
bra
W0,W2
LEU,UI2NUM_FIN
UI2NUM_ERR:
mov
#0x0002,W1
call
NEWLINE_DISPLAY
mov
mov
call
#UI2NUMERR,W2
#30,W1
STRING_DISPLAY
;User Input is fine, number returned in W1,W0
;Restore stack
;
;
;
;UIH == MAXH?
;UI > MAX... issue an error and restart
;UIH == MAXH, Check low bytes
;UIL > MAXL?
;no, everything is good
;UI > MAX... issue an error and restart
;2 New lines
;
;Send out error message
;
;
bclr
SR,#15
;Clear OA bit
pop
pop
W0
W2
;Restore original values
;
141
pop
W1
goto
UI2NUM
;---------UI2NUM_SF:
Mov
#0x0000,W0
mov.b W0,[W3++]
dec
W2,W2
bra
UI2NUM_FC
;
;rinse and repeat
;0's left to fill
;Fill one digit
;
;decrement 0 fill counter
;check if more filling required
UI2NUM_DF:
;Digits left to fill
mov.b [W4++],W0
;Retrieve one digit
sub.b #0x30,W0
;Get rid of ASCII coding
mov.b W0,[W3++]
;place digit into string
dec
W2,W2
;decrement digit fill counter
bra
UI2NUM_DC
;check if more filling required
;*********************************************************
;*********************************************************
;ODEBUG_DISPLAY Orientation Debug Display Routine
;
;Displays sensor data in easy to read format that is
;output via the UART port.
;*********************************************************
ODEBUG_DISPLAY:
mov
#DEBUG_MAG,W2
;Send out Mag Identifier
mov
#0x001C,W1
;
call
STRING_DISPLAY
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
call
#0x0006,W1
SPACE_DISPLAY
;Spaces
;
mov
mov
call
#MAG_CSV,W2
#0x0016,W1
STRING_DISPLAY
;Send out Mag Data
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_TILT,W2
#0x001C,W1
STRING_DISPLAY
;Send out Tilt Identifier
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
call
#0x0006,W1
SPACE_DISPLAY
;Spaces
;
mov
mov
call
#TILT_CSV,W2
#0x000E,W1
STRING_DISPLAY
;Send out Tilt Data
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
return
;
;*********************************************************
;*********************************************************
;ADEBUG_DISPLAY Acoustic Debug Display Routine
;
;Displays acoustic data in easy to read format that is
142
;output via the UART port.
;*********************************************************
ADEBUG_DISPLAY:
mov
#DEBUG_A1,W2
;Send out Range Identifier
mov
#0x000C,W1
;
call
STRING_DISPLAY
;
mov
mov
call
#AP_CSV,W2
#0x000A,W1
STRING_DISPLAY
;Send out Range Information
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_A2,W2
#0x000C,W1
STRING_DISPLAY
;Send out Order Identifier
;
;
mov
mov
call
#AP_CSV+#0xC,W2
#0x0001,W1
STRING_DISPLAY
;Send out Order Information
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_A3,W2
#0x000C,W1
STRING_DISPLAY
;Send out Tran1 Identifier
;
;
mov
mov
call
#AP_CSV+#0xF,W2
#0x0005,W1
STRING_DISPLAY
;Send out Tran1 Information
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_A4,W2
#0x000C,W1
STRING_DISPLAY
;Send out Tran2 Identifier
;
;
mov
mov
call
#AP_CSV+#0x16,W2
#0x0005,W1
STRING_DISPLAY
;Send out Tran2 Information
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_A5,W2
#0x000C,W1
STRING_DISPLAY
;Send out Tran3 Identifier
;
;
mov
mov
call
#AP_CSV+#0x1D,W2
#0x0005,W1
STRING_DISPLAY
;Send out Tran3 Information
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_A6,W2
#0x000C,W1
STRING_DISPLAY
;Send out Stime Identifier
;
;
mov
#TIME_CSV,W2
;Send out Stime Information
143
mov
call
#0x000A,W1
STRING_DISPLAY
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_A7,W2
#0x000C,W1
STRING_DISPLAY
;Send out Etime Identifier
;
;
mov
mov
call
#TIME_CSV+#0x0C,W2
#0x000A,W1
STRING_DISPLAY
;Send out Etime Information
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
return
;
;*********************************************************
;*********************************************************
;OT_DISPLAY Orientation Time Display Routine
;
;Displays sensor time data in easy to read format that is
;output via the UART port.
;*********************************************************
OT_DISPLAY:
mov
#DEBUG_MAGT,W2
;Send out Mag Time Identifier
mov
#0x000C,W1
;
call
STRING_DISPLAY
;
mov
mov
call
#TIME_CSV+#36,W2
#0x000A,W1
STRING_DISPLAY
;Send out Mag Time Data
;
;
mov
call
#0x0001,W1
NEWLINE_DISPLAY
;New line
;
mov
mov
call
#DEBUG_TILTT,W2
#0x000C,W1
STRING_DISPLAY
;Send out Tilt Time Identifier
;
;
mov
mov
call
#TIME_CSV+#24,W2
#0x000A,W1
STRING_DISPLAY
;Send out Tilt Time Data
;
;
return
;
;*********************************************************
;*********************************************************
;VAL_DISPLAY Setup Values Display Routine
;
;Displays setup values in easy to read format that is
;output via the UART port.
;*********************************************************
VAL_DISPLAY:
call
VAL_DF
;Update display strings with current values
mov
mov
call
mov
call
#VALDISP1,W2
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
;Send out first line
;
;
;New line
;
mov
#VALDISP2,W2
;Send out next line
144
mov
call
mov
call
mov
mov
call
mov
call
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
#VALDISP3,W2
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
;
;
;New line
;
;Send out next line
;
;
;New line
;
mov
mov
call
mov
call
#VALDISP4,W2
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
;Send out next line
;
;
;New line
;
mov
mov
call
mov
call
#VALDISP5,W2
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
;Send out next line
;
;
;New line
;
mov
mov
call
mov
call
#VALDISP6,W2
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
;Send out next line
;
;
;New line
;
mov
mov
call
mov
call
#VALDISP7,W2
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
;Send out next line
;
;
;New line
;
mov
mov
call
mov
call
#VALDISP8,W2
#28,W1
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
;Send out next line
;
;
;New line
;
mov
mov
call
mov
call
#VALDISP9,W2
#28,W1
STRING_DISPLAY
#0x0002,W1
NEWLINE_DISPLAY
;Send out last line
;
;
;New line
;
return
;
;*********************************************************
;*********************************************************
;VAL_DF Setup Values Data Format
;
;Updates setup value display strings with the current
;values of the setup parameters.
;*********************************************************
VAL_DF:
mov
#VALDISP1+#12,W13
;load W13 starting memory location
mov
AP_PRE1,W0
;Retrieve current value
call
num2ascii
;Convert Number to ASCII Character Array
mov.b
W3,[W13++]
;Insert current value into display string
mov.b
W2,[W13++]
;
mov.b
W1,[W13++]
;
mov
#VALDISP2+#12,W13
;load W13 starting memory location
145
mov
call
mov.b
mov.b
mov.b
AP_PRE2,W0
num2ascii
W3,[W13++]
W2,[W13++]
W1,[W13++]
;Retrieve current value
;Convert Number to ASCII Character Array
;Insert current value into display string
;
;
mov
mov
call
mov.b
mov.b
mov.b
#VALDISP3+#12,W13
AP_PRE3,W0
num2ascii
W3,[W13++]
W2,[W13++]
W1,[W13++]
;load W13 starting memory location
;Retrieve current value
;Convert Number to ASCII Character Array
;Insert current value into display string
;
;
mov
mov
call
mov.b
mov.b
mov.b
#VALDISP4+#12,W13
AP_POST1,W0
num2ascii
W3,[W13++]
W2,[W13++]
W1,[W13++]
;load W13 starting memory location
;Retrieve current value
;Convert Number to ASCII Character Array
;Insert current value into display string
;
;
mov
mov
call
mov.b
mov.b
mov.b
#VALDISP5+#12,W13
AP_POST2,W0
num2ascii
W3,[W13++]
W2,[W13++]
W1,[W13++]
;load W13 starting memory location
;Retrieve current value
;Convert Number to ASCII Character Array
;Insert current value into display string
;
;
mov
mov
call
mov.b
mov.b
mov.b
#VALDISP6+#12,W13
AP_POST3,W0
num2ascii
W3,[W13++]
W2,[W13++]
W1,[W13++]
;load W13 starting memory location
;Retrieve current value
;Convert Number to ASCII Character Array
;Insert current value into display string
;
;
mov
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
#VALDISP7+#12,W13
AP_TPNC,W0
num2ascii
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
;load W13 starting memory location
;Retrieve current reading
;Convert Number to ASCII Character Array
;Insert current value into display string
;
;
;
;
mov
mov
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
#VALDISP8+#12,W13
AP_BIGTOH,W1
AP_BIGTOL,W0
bnum2ascii
W10,[W13++]
W9,[W13++]
W8,[W13++]
W7,[W13++]
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
;load W13 starting memory location
;Retrieve current reading
;
;Convert Number to ASCII Character Array
;Insert current value into display string
;
;
;
;
;
;
;
;
;
mov
mov
mov
call
mov.b
#VALDISP9+#12,W13
AP_SMALLTOH,W1
AP_SMALLTOL,W0
bnum2ascii
W10,[W13++]
;load W13 starting memory location
;Retrieve current reading
;
;Convert Number to ASCII Character Array
;Insert current value into display string
146
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
W9,[W13++]
W8,[W13++]
W7,[W13++]
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
;
;
;
;
;
;
;
;
;
return
;
;*********************************************************
;*********************************************************
;STRING_DISPLAY String Display Routine
;
;Sends a string out the UART. The string starting
;location is passed in W2, the number of charactors to
;send out is passed in W1.
;*********************************************************
STRING_DISPLAY:
cp0
W1
;Check if there are still
bra
NZ,SD_SENDOUT
;characters left to send
return
;no
SD_SENDOUT:
;Characters left to send out
mov.b
[W2++],W0
;Send character out UART2
call
U2_Transmit
;
dec
W1,W1
;
bra
STRING_DISPLAY
;
;*********************************************************
;*********************************************************
;SPACE_DISPLAY Space Display Routine
;
;Sends a specified number of space characters out through
;UART2. The number of spaces is passed through W1.
;*********************************************************
SPACE_DISPLAY:
cp0
W1
;Check if there are still
bra
NZ,SPD_SENDOUT
;spaces left to send
return
;no
SPD_SENDOUT:
;Spaces left to send out
mov
#0x0020,W0
;Send space out UART2
call
U2_Transmit
;
dec
W1,W1
;
bra
SPACE_DISPLAY
;
;*********************************************************
;*********************************************************
;CLEAR_DISPLAY Clear Display Routine
;
;Sends out the Clear display ANSI command <ESC>[2J
;*********************************************************
CLEAR_DISPLAY:
mov
#0x001B,W0
;Send ESC out UART2
call
U2_Transmit
;
mov
#0x005B,W0
;Send [ out UART2
call
U2_Transmit
;
mov
#0x0032,W0
;Send 2 out UART2
call
U2_Transmit
;
mov
#0x004A,W0
;Send J out UART2
call
U2_Transmit
;
return
;no
;*********************************************************
;*********************************************************
;NEWLINE_DISPLAY New Line Display Routine
147
;
;Sends a specified number of new Line characters out through
;UART2. The number of new lines is passed through W1.
;*********************************************************
NEWLINE_DISPLAY:
cp0
W1
;Check if there are still
bra
NZ,NL_SENDOUT
;new lines left to send
return
;no
NL_SENDOUT:
;new lines left to send out
mov
#0x000D,W0
;CR
call
U2_Transmit
;
mov
#0x000A,W0
;LF
call
U2_Transmit
;
dec
W1,W1
;
bra
NEWLINE_DISPLAY
;
;*********************************************************
;*********************************************************
;HOME_DISPLAY Put Cursor to Home Position Routine
;
;Sends out the Home ANSI command ESC[#;#H
;*********************************************************
HOME_DISPLAY:
mov
#0x001B,W0
;Send ESC out UART2
call
U2_Transmit
;
mov
#0x005B,W0
;Send [ out UART2
call
U2_Transmit
;
mov
#0x0030,W0
;Send 0 out UART2
call
U2_Transmit
;
mov
#0x003B,W0
;Send ; out UART2
call
U2_Transmit
;
mov
#0x0030,W0
;Send 0 out UART2
call
U2_Transmit
;
mov
#0x0048,W0
;Send H out UART2
call
U2_Transmit
;
return
;no
;*********************************************************
;********Data Format Routines*********************************
;*********************************************************
;MAG_DF Magnetometer Data Format
;
;Converts magnetometer data into an ASCII Character Array
;and stores the readings as CSVs in data memory
;*********************************************************
MAG_DF:
mov
#MAG_CSV,W13
;load W13 starting memory location
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
XMAG,W0
snum2ascii
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;Retrieve X-axis reading
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;', ' (Comma,Space)
;
mov
call
mov.b
YMAG,W0
snum2ascii
W6,[W13++]
;Retrieve Y-axis reading
;Convert Number to ASCII Character Array
;
148
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;
;
;
;
;
;', ' (Comma,Space)
;
mov
ZMAG,W0
;Retrieve Z-axis reading
call
snum2ascii
;Convert Number to ASCII Character Array
mov.b
W6,[W13++]
;
mov.b
W5,[W13++]
;
mov.b
W4,[W13++]
;
mov.b
W3,[W13++]
;
mov.b
W2,[W13++]
;
mov.b
W1,[W13++]
;
return
;
;*********************************************************
;*********************************************************
;TILT_DF Tilt Data Format
;
;Converts tilt data into an ASCII Character Array and
;stores the readings as CSVs in data memory
;*********************************************************
TILT_DF:
mov
#TILT_CSV,W13
;load W13 starting memory location
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
XTilt,W0
snum2ascii
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;Retrieve X-tilt reading
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;', ' (Comma,Space)
;
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
YTilt,W0
snum2ascii
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;Retrieve Y-Tilt reading
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;', ' (Comma,Space)
;
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
XAccel,W0
snum2ascii
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;Retrieve X-Accel reading
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;', ' (Comma,Space)
;
mov
call
mov.b
YAccel,W0
snum2ascii
W6,[W13++]
;Retrieve Y-Accel reading
;Convert Number to ASCII Character Array
;
149
mov.b
W5,[W13++]
;
mov.b
W4,[W13++]
;
mov.b
W3,[W13++]
;
mov.b
W2,[W13++]
;
mov.b
W1,[W13++]
;
return
;
;*********************************************************
;*********************************************************
;AP_DF Acoustic Processor Data Format
;
;Converts AP data into an ASCII Character Array and
;stores the readings as CSVs in data memory
;*********************************************************
AP_DF:
mov
#AP_CSV,W13
;load W13 starting memory location
mov
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
AP_RANGEH,W1
AP_RANGEL,W0
bnum2ascii
W10,[W13++]
W9,[W13++]
W8,[W13++]
W7,[W13++]
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;Retrieve Range reading
;
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;
;
;
;
;', ' (Comma,Space)
;
mov
call
mov.b
mov
mov.b
mov
mov.b
AP_TRANSORDER,W0
num2ascii
W1,[W13++]
#0x002C,W0
W0,[W13++]
#0x0020,W0
W0,[W13++]
;Retrieve TRANSORDER reading
;Convert Number to ASCII Character Array
;(0-7 are only possible values)
;
;', ' (Comma,Space)
;
;
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov.b
mov
mov.b
AP_TRANS1,W0
num2ascii
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x002C,W0
W0,[W13++]
#0x0020,W0
W0,[W13++]
;Retrieve Trans1 reading
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;', ' (Comma,Space)
;
;
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov.b
mov
mov.b
AP_TRANS2,W0
num2ascii
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x002C,W0
W0,[W13++]
#0x0020,W0
W0,[W13++]
;Retrieve Trans2 reading
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;', ' (Comma,Space)
;
;
150
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
AP_TRANS3,W0
num2ascii
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
;Retrieve Trans3 reading
;Convert Number to ASCII Character Array
;
;
;
;
;
return
;
;*********************************************************
;*********************************************************
;TIME_DF TIME Data Format
;
;Converts TIME data into an ASCII Character Array and
;stores the readings as CSVs in data memory
;*********************************************************
TIME_DF:
mov
#TIME_CSV,W13
;load W13 starting memory location
mov
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
AP_STIMEH,W1
AP_STIMEL,W0
bnum2ascii
W10,[W13++]
W9,[W13++]
W8,[W13++]
W7,[W13++]
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;
;
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;
;
;
;
;', ' (Comma,Space)
;
mov
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov
mov
AP_ETIMEH,W1
AP_ETIMEL,W0
bnum2ascii
W10,[W13++]
W9,[W13++]
W8,[W13++]
W7,[W13++]
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;
;
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;
;
;
;
;', ' (Comma,Space)
;
mov
mov
call
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
mov.b
TILT_TIMEH,W1
TILT_TIMEL,W0
bnum2ascii
W10,[W13++]
W9,[W13++]
W8,[W13++]
W7,[W13++]
W6,[W13++]
W5,[W13++]
W4,[W13++]
W3,[W13++]
;
;
;Convert Number to ASCII Character Array
;
;
;
;
;
;
;
;
151
mov.b
mov.b
mov
mov
W2,[W13++]
W1,[W13++]
#0x202C,W0
W0,[W13++]
;
;
;', ' (Comma,Space)
;
mov
MAG_TIMEH,W1
;
mov
MAG_TIMEL,W0
;
call
bnum2ascii
;Convert Number to ASCII Character Array
mov.b
W10,[W13++]
;
mov.b
W9,[W13++]
;
mov.b
W8,[W13++]
;
mov.b
W7,[W13++]
;
mov.b
W6,[W13++]
;
mov.b
W5,[W13++]
;
mov.b
W4,[W13++]
;
mov.b
W3,[W13++]
;
mov.b
W2,[W13++]
;
mov.b
W1,[W13++]
;
return
;
;*********************************************************
;*********************************************************
;sensor_data_write
SENSOR DATA WRITE
;
;Sends out all the sensor data in a comma delimited string
;out the UART2 port
;*********************************************************
sensor_data_write:
mov
#0x0024,W0
;'$UWGPS'
call
U2_Transmit
;
mov
#0x0055,W0
;
call
U2_Transmit
;
mov
#0x0057,W0
;
call
U2_Transmit
;
mov
#0x0047,W0
;
call
U2_Transmit
;
mov
#0x0050,W0
;
call
U2_Transmit
;
mov
#0x0053,W0
;
call
U2_Transmit
;
mov
call
mov
call
mov
mov
call
#0x002C,W0
U2_Transmit
#0x0020,W0
U2_Transmit
#MAG_CSV,W2
#22,W1
STRING_DISPLAY
;', ' (Comma,Space)
;
;
;
;Send out Mag Data
;
;
mov
call
mov
call
#0x002C,W0
U2_Transmit
#0x0020,W0
U2_Transmit
;', ' (Comma,Space)
;
;
;
mov
mov
call
#TILT_CSV,W2
#14,W1
STRING_DISPLAY
;Send out Tilt Data
;
;
mov
call
mov
call
#0x002C,W0
U2_Transmit
#0x0020,W0
U2_Transmit
;', ' (Comma,Space)
;
;
;
152
mov
mov
call
mov
call
mov
call
mov
mov
call
#AP_CSV,W2
#34,W1
STRING_DISPLAY
#0x002C,W0
U2_Transmit
#0x0020,W0
U2_Transmit
#TIME_CSV,W2
#46,W1
STRING_DISPLAY
;Send out AP Data
;
;
;', ' (Comma,Space)
;
;
;
;Send out Time Data
;
;
mov
#0x002C,W0
;', ' (Comma,Space)
call
U2_Transmit
;
mov
#0x0020,W0
;
call
U2_Transmit
;
return
;
;*********************************************************
;*************************************************************
;********SPI Routines*****************************************
;*********************************************************
;SPI_INIT SPI Initialization
;*********************************************************
SPI_INIT:
clr
SPIRNUM
;Clear Counters
clr
SPITNUM
;
clr
SPIFLAGS
;Clear Flags
bset
AP_TRIS,#AP_SS
;Use SS pin to find out if
;data is ready
bclr
PMD1,#SPI2MD
;Make sure module isn't disabled
clr
SPI2BUF
;Clear SPIxBUF register
;if using interrupts:
;
bclr
IFS2,#SPI2IF
;
nop
bclr
IFS2,#SPI2EIF
;
nop
;
bset
IEC2,#SPI2IE
;
nop
;
bset
IEC2,#SPI2EIE
;
bset
IPC8,#9
;Set Interrupt Priority 3
nop
;
bclr
IPC8,#10
;
nop
;
bset
IPC8,#8
;
;
mov
#0x043F,W0
;Setup 1st SPI Control Register 1:1 Clock
mov
#0x043D,W0
;Setup 1st SPI Control Register 1:16 clock
mov
W0,SPI2CON1
;Master Mode,
mov
#0x0000,W0
;Setup 2nd SPI Control Register
mov
W0,SPI2CON2
;No framed SPI support
bclr
SPI2STAT,#SPIROV
;Clear SPIROV bit
nop
;
bset
SPI2STAT,#SPIEN
;Enable SPI Operation
return
;
;*********************************************************
;*********************************************************
;__SPI2Interrupt SPI Interrupt Routine
;*********************************************************
__SPI2Interrupt:
push
W0
;
push
W1
;
push
W2
;
153
bclr
bclr
IFS2,#SPI2IF
SPIFLAGS,#0
;Clear Interrupt Flag
;Clear SPI Interrupt Occurred? Flag
cp0
bra
SPITNUM
NZ,SPIINTTRANSMIT
;Check if any data to be transmitted
;
rlnc
mov
add
SPIRNUM,WREG
#SPIRECEIVE,W1
W0,W1,W2
;Load Address Location
;
;
mov
mov
SPI2BUF,W0
W0,[W2++]
;Retrieve word
;Save received word
inc
SPIRNUM
SPIINTRETURN:
pop
W2
pop
W1
pop
W0
retfie
;Increment Received Word Count
;
;
;
;
SPIINTTRANSMIT:
dec
SPITNUM
;decrement Transmit Counter
mov
SPI2BUF,W0
;Read data out to prevent overflow
goto
SPIINTRETURN
;
;*********************************************************
;*********************************************************
;__SPI1ErrInterrupt SPI ERROR Interrupt
;
;If an SPI overflow occurs, overflow flag must be cleared
;to re-enable reception
;*********************************************************
__SPI2ErrInterrupt:
bclr
IFS2,#SPI2EIF
;Clear interrupt flag
bclr
SPI2STAT,#SPIROV
;Clear SPIROV bit
retfie
;
;*********************************************************
;*********************************************************
;SPI_WRITE SPI Word Write
;
;Data to be written is to be stored at location SPITRANSMIT
;Number of words to be written stored in SPITNUM
;*********************************************************
SPI_WRITE:
mov
#SPITRANSMIT,W2
;Load start address
SPI_REWRITE:
cp0
SPITNUM
;Check if any data to be transmitted
bra
NZ,SPI_WRITEWORD
;
return
;no data to send
SPI_WRITEWORD:
bset
SPIFLAGS,#0
;Set interrupt check flag
mov
[W2++],W0
;
mov
W0,SPI2BUF
;Send Received word out
nop
;
SPI_WRITE_WAIT:
btsc
SPIFLAGS,#0
;Transfer occur yet?
goto
SPI_WRITE_WAIT
;no
goto
SPI_REWRITE
;yes
;*********************************************************
;*********************************************************
;SPI_READ SPI Word READ
;
;Waits until slave has data to read, it then reads all of
;it
154
;*********************************************************
SPI_READ:
nop
btss
AP_PORT,#AP_SS
;Check if any data needs to be read
goto
SPI_READ
;no data to read yet, wait
SPI_READWORD:
bset
SPIFLAGS,#0
;Set interrupt check flag
mov
0x0000,W0
;Send blank word
mov
W0,SPI2BUF
;in order to initiate transfer
nop
;
SPI_READ_WAIT:
btsc
SPIFLAGS,#0
;Transfer occur yet?
goto
SPI_READ_WAIT
;no
nop
;Give slave a little
nop
;time to clear data
nop
;ready flag
nop
;
nop
;
nop
;
nop
;
btss
AP_PORT,#AP_SS
;Check if any more data needs to be read
return
;no, finished
goto
SPI_READWORD
;yes
;*********************************************************
;*********************************************************
;AP_INIT Acoustic Processor Initialization
;
;Setup default values for AP components
;*********************************************************
AP_INIT:
mov
#45,W0
;Transmit Number of Cycles
mov
W0,AP_TPNC
;
mov
#0x007F,W0
;Pre-Amp 1 Gain
mov
W0,AP_PRE1
;
mov
#0x007F,W0
;Pre-Amp 2 Gain
mov
W0,AP_PRE2
;
mov
#0x007F,W0
;Pre-Amp 3 Gain
mov
W0,AP_PRE3
;
mov
#0x007F,W0
;Post-Amp 1 Gain
mov
W0,AP_POST1
;
mov
#0x007F,W0
;Post-Amp 2 Gain
mov
W0,AP_POST2
;
mov
#0x007F,W0
;Post-Amp 3 Gain
mov
W0,AP_POST3
;
mov
#0x0131,W0
;Big Timeout High Word
mov
W0,AP_BIGTOH
;
mov
#0x2D00,W0
;Big Timeout Low Word
mov
W0,AP_BIGTOL
;
mov
#0x0000,W0
;Small Timeout High Word
mov
W0,AP_SMALLTOH
;
mov
#0x4E20,W0
;Small Timeout Low Word
mov
W0,AP_SMALLTOL
;
clr
AP_COMMAND
;Error occurred,
clr
AP_RANGEH
;clear all data
clr
AP_RANGEL
;
clr
AP_TRANS1
;
clr
AP_TRANS2
;
clr
AP_TRANS3
;
clr
AP_TRANSORDER
;
return
;done
;*********************************************************
;*********************************************************
155
;AP_GM Acoustic Processor Get Measurement
;
;Request that the AP start getting a range and bearing
;measurement. It should then signal the AP_SS line when
;data is ready.
;*********************************************************
AP_GM:
mov
#0X474D,W0
;'GM' - Command
mov
W0,SPITRANSMIT
;
mov
#0x0001,W0
;Set Number of bytes
mov
W0,SPITNUM
;to send out
call
SPI_WRITE
;Send Command
return
;done
;*********************************************************
;*********************************************************
;AP_GM_READ Acoustic Processor Get Measurement Read
;
;Wait for AP data to be ready, then retrieve it and parse
;it into data memory
;*********************************************************
AP_GM_READ:
call
SPI_READ
;Wait, then read in AP data
mov
#0x0007,W0
;Check that at least 7 words
cp
SPIRNUM
;were received
bra
LTU,APGMREAD_ERROR
;if not, error
;enough data received, parse data out
mov
#SPIRECEIVE,W2
;Load start address
mov
[W2++],W0
;
mov
W0,AP_COMMAND
;
mov
[W2++],W0
;
mov
W0,AP_RANGEH
;
mov
[W2++],W0
;
mov
W0,AP_RANGEL
;
mov
[W2++],W0
;
mov
W0,AP_TRANSORDER
;
mov
[W2++],W0
;
mov
W0,AP_TRANS1
;
mov
[W2++],W0
;
mov
W0,AP_TRANS2
;
mov
[W2++],W0
;
mov
W0,AP_TRANS3
;
clr
SPIRNUM
;Clear receive buffer count
return
;done
APGMREAD_ERROR:
clr
AP_COMMAND
;Error occurred,
clr
AP_RANGEH
;clear all data
clr
AP_RANGEL
;
clr
AP_TRANS1
;
clr
AP_TRANS2
;
clr
AP_TRANS3
;
clr
AP_TRANSORDER
;
return
;
;*********************************************************
;*********************************************************
;AP_GB Acoustic Processor Get Bearing
;
;Request that the AP start getting a bearing
;measurement. It should then signal the AP_SS line when
;data is ready.
;*********************************************************
AP_GB:
mov
#0X4742,W0
;'GB' - Command
mov
W0,SPITRANSMIT
;
156
mov
#0x0001,W0
;Set Number of bytes
mov
W0,SPITNUM
;to send out
call
SPI_WRITE
;Send Command
return
;done
;*********************************************************
;*********************************************************
;AP_GB_READ Acoustic Processor Get Bearing Read
;
;Wait for AP data to be ready, then retrieve it and parse
;it into data memory
;*********************************************************
AP_GB_READ:
call
SPI_READ
;Wait, then read in AP data
mov
#0x0005,W0
;Check that at least 5 words
cp
SPIRNUM
;were received
bra
LTU,APGBREAD_ERROR
;if not, error
;enough data received, parse data out
mov
#SPIRECEIVE,W2
;Load start address
mov
[W2++],W0
;
mov
W0,AP_COMMAND
;
mov
[W2++],W0
;
mov
W0,AP_TRANSORDER
;
mov
[W2++],W0
;
mov
W0,AP_TRANS1
;
mov
[W2++],W0
;
mov
W0,AP_TRANS2
;
mov
[W2++],W0
;
mov
W0,AP_TRANS3
;
clr
AP_RANGEH
;clear range (not used)
clr
AP_RANGEL
;
clr
SPIRNUM
;Clear receive buffer count
return
;done
APGBREAD_ERROR:
clr
AP_COMMAND
;Error occurred,
clr
AP_RANGEH
;clear all data
clr
AP_RANGEL
;
clr
AP_TRANS1
;
clr
AP_TRANS2
;
clr
AP_TRANS3
;
clr
AP_TRANSORDER
;
return
;
;*********************************************************
;*********************************************************
;AP_TP Acoustic Processor Transmit Pulse
;
;Request that the AP transmit a pulse of length determined
;by AP_TPNC.
;*********************************************************
AP_TP:
mov
#SPITRANSMIT,W2
;Set Message Address
mov
#0X5450,W0
;'TP' - Command
mov
W0,[W2++]
;
mov
AP_TPNC,W0
;Number of Transmit Cycles
mov
W0,[W2++]
;
mov
#0x0002,W0
;Set Number of bytes
mov
W0,SPITNUM
;to send out
call
SPI_WRITE
;Send Command
return
;done
;*********************************************************
;*********************************************************
;AP_SP Acoustic Processor Set Parameters
;
;Send out new parameters to acoustic board
157
;*********************************************************
AP_SP:
mov
#SPITRANSMIT,W2
;Set Message Address
mov
#0X5350,W0
;'SP' - Command
mov
W0,[W2++]
;
mov
AP_TPNC,W0
;Number of Transmit Cycles
mov
W0,[W2++]
;
mov
AP_PRE1,W0
;Pre-Amp 1 Gain
mov
W0,[W2++]
;
mov
AP_PRE2,W0
;Pre-Amp 2 Gain
mov
W0,[W2++]
;
mov
AP_PRE3,W0
;Pre-Amp 3 Gain
mov
W0,[W2++]
;
mov
AP_POST1,W0
;Post-Amp 1 Gain
mov
W0,[W2++]
;
mov
AP_POST2,W0
;Post-Amp 2 Gain
mov
W0,[W2++]
;
mov
AP_POST3,W0
;Post-Amp 3 Gain
mov
W0,[W2++]
;
mov
AP_BIGTOH,W0
;Big Timeout High Word
mov
W0,[W2++]
;
mov
AP_BIGTOL,W0
;Big Timeout Low Word
mov
W0,[W2++]
;
mov
AP_SMALLTOH,W0
;Small Timeout High Word
mov
W0,[W2++]
;
mov
AP_SMALLTOL,W0
;Small Timeout Low Word
mov
W0,[W2++]
;
mov
#0x000C,W0
;Set Number of bytes
mov
W0,SPITNUM
;to send out
call
SPI_WRITE
;Send Command
return
;done
;*********************************************************
;*************************************************************
;********Timer Routines***************************************
;*********************************************************
;Timer23_init - Timers 2/3 Init (use as a 32-bit timer)
;
;Setup Timer 2/3 to operated as a single 32-bit timer
;*********************************************************
Timer23_init:
bclr
PMD1,#12
;Enable Timer 2/3 Modules
bclr
PMD1,#13
;
clr
T2CON
;
clr
T3CON
;
mov
#0xFFFF,W0
;Allow for Maximum Count
mov
W0,PR3
;
mov
W0,PR2
;
;mov
#0x0038,W0
;Setup 32-bit timer (1:256 prescaler)
mov
#0x0008,W0
;Setup 32-bit timer (1:1 prescaler)
mov
W0,T2CON
;(Timer 2/3)
;Not setting up any interrupts
nop
bset
T2CON,#15
;start timer
return
;
;*********************************************************
;*********************************************************
;Timer23_clear - Timers 2/3 Clear
;
;Clear 32-bit timer (Start at 0x00000000)
;*********************************************************
Timer23_clear:
;
158
mov
#0x0000,W0
;Write 0x0000 to MSW
mov
W0,TMR3HLD
;(Timer 2/3)
mov
W0,TMR2
;(Timer 2/3)
return
;
;*********************************************************
;*********************************************************
;Timer23_read - Timers 2/3 Read
;
;Read the 32-bit timer
;*********************************************************
Timer23_read:
mov
TMR2,W0
;Transfer the LSW into W0
mov
TMR3HLD, W1
;Transfer the MSW from the
;holding register to W1
return
;
;*********************************************************
;*********************************************************
;OnePPS_init - 1PPS Init (INT4)
;
;Setup 1PPS pin as input and interrupt used to clear timer
;*********************************************************
OnePPS_init:
bset
INT_TRIS,#GPS_INT
;Set 1PPS pin as an input
;Setup INT4 interrupt
bclr
INTCON2,#INT4EP
;Interrupt on positive edge
bset
IPC13,#9
;Set interrupt priority
;to level 6 (default level 4)
bclr
INTCON1,#NSTDIS
;Enable nested interrupts
bclr
IFS3,#INT4IF
;Clear interrupt flag
bset
IEC3,#INT4IE
;Enable INT4 interrupt
return
;
;*********************************************************
;*********************************************************
;__INT4Interrupt - INT4 Interrupt Routine (1PPS)
;
;Clears Timer2/3 when 1PPS interrupt is received
;*********************************************************
__INT4Interrupt:
;Save context
push
W0
;Save W0
push
W1
;
push
W2
;
;Clear Timer 2/3 value
mov
#0x0000,W0
;Write 0x0000 to MSW
mov
W0,TMR3HLD
;(Timer 2/3)
mov
W0,TMR2
;(Timer 2/3)
bset
MAIN_FLAGS,#0
;Set 1PPS Flag
btss
MAIN_FLAGS,#1
;Send out Debug "[PPS]"?
goto
int4_exit
;no
mov
#GPSPPS,W2
;yes, Send out PPS message
mov
#5,W1
;"[PPS]"
call
STRING_DISPLAY
;
mov
#0x0001,W1
;New line
call
NEWLINE_DISPLAY
;
int4_exit:
;Restore context
pop
W2
;
pop
W1
;
pop
W0
;Restore W0
bclr
IFS3,#INT4IF
;Clear interrupt flag
retfie
;return
;*********************************************************
159
;*************************************************************
;********Tilt Sensor Routines*********************************
;*********************************************************
;tilt_init - Tilt Init Routine
;
;Initialize tilt sensor pins
;*********************************************************
Tilt_init:
;SCLK
bclr
XL_TRIS,#XL_SCLK
;Set inputs and outputs
bset
XL_PORT,#XL_SCLK
;
;DIN
bclr
XL_TRIS,#XL_DIN
;
bclr
XL_PORT,#XL_DIN
;
;DOUT
bset
XL_TRIS,#XL_DOUT
;
nop
;CS(Bar)
bclr
XL_TRIS,#XL_CS
;
bset
XL_PORT,#XL_CS
;
;AUX DIO0
bset
XL_TRIS,#XL_DIO0
;
return
;
;*********************************************************
;****Tilt Sensor Setup**************************
Tilt_Setup:
mov
#0xB804,W0
;Set AVG_CNT filter to 16 taps
call
Tilt_RW
;
mov
#0xB684,W0
;Set Sample Period to ~15ms
call
Tilt_RW
;equates to about 0.25sec measurement
;with 16 taps window average
mov
#0xB406,W0
;Set DIO0 line to be active high Data
call
Tilt_RW
;Ready Line
return
;***********************************************
;****Tilt Sensor Zero***************************
Tilt_Zero:
mov
#0xBE01,W0
;Tell Sensor to zero its offsets
call
Tilt_RW
;
return
;***********************************************
;****Tilt Data Mask*****************************
Tilt_Data_Mask:
;Tilt Values should only be 12-bits
mov
#0x0FFF,W0
;Mask off 12 bit value for Tilt
and
XTilt
;
and
YTilt
;
mov
#0xF000,W0
;Extend Sign bit if present
btsc
XTilt,#11
;
ior
XTilt
;
btsc
YTilt,#11
;
ior
YTilt
;
;Acceleration Values should be 14-bits
mov
#0x3FFF,W0
;Mask off 14 bit value
and
XAccel
;
and
YAccel
;
mov
#0xC000,W0
;Extend Sign bit if present
btsc
XAccel,#13
;
ior
XAccel
;
btsc
YAccel,#13
;
ior
YAccel
;
160
return
;
;***********************************************
;****Tilt Sensor Read Data**********************
Tilt_Read:
mov
#0x0D00,W0
;Send out read command
call
Tilt_RW
;
mov
#0x0F00,W0
;Send out read command
call
Tilt_RW
;
mov
W1,XTilt
;Retrieve X-Tilt
mov
#0x0500,W0
;Send out read command
call
Tilt_RW
;
mov
W1,YTilt
;Retrieve Y-Tilt
mov
#0x0700,W0
;Send out read command
call
Tilt_RW
;
mov
W1,XAccel
;Retrieve X-Accel
mov
#0x0B00,W0
;Send out read command
collected)
call
Tilt_RW
;
mov
W1,YAccel
;Retrieve Y-Accel
return
;
;***********************************************
;****Tilt Read Write****************************
;W0 includes Command Word (chooses register to read)
Tilt_RW:
bclr
XL_PORT,#XL_CS
;CSbar low
;W0 should have COMMAND BYTE
call
Tilt_Shift
;Shift out Command Word
;Receive Data Word in W1
bset
XL_PORT,#XL_CS
;CSbar high
call
delay71us
;delay to satisfy timing
return
;Return with Data in W1
;***********************************************
;****Tilt Clock Pulse***************************
Tilt_Clock_Pulse:
bclr
XL_PORT,#XL_SCLK
;Clock Pin Low
nop
;
nop
;
bset
XL_PORT,#XL_SCLK
;Clock Pin High
return
;
;***********************************************
;****Tilt Shift*********************************
Tilt_Shift:
;Clear output variable W1
clr
W1
;
;Begin Shifting Data
bclr
XL_PORT,#XL_DIN
;Assume Bit Clear
btsc
W0,#15
;Send out MSB
bset
XL_PORT,#XL_DIN
;Bit Set
call
Tilt_Clock_Pulse
;Clock bit through
btsc
XL_PORT,#XL_DOUT
;Read in MSB
bset
W1,#15
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#14
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#14
;Assume Bit Clear
;Send out bit #14
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
XL_PORT,#XL_DIN
W0,#13
;Assume Bit Clear
;Send out bit #13
for X-Tilt
for Y-Tilt
for X-Accel
for Y-Accel
for Temp (never
161
bset
call
btsc
bset
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#13
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#12
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#12
;Assume Bit Clear
;Send out bit #12
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#11
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#11
;Assume Bit Clear
;Send out bit #11
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#10
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#10
;Assume Bit Clear
;Send out bit #10
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#9
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#9
;Assume Bit Clear
;Send out bit #9
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#8
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#8
;Assume Bit Clear
;Send out bit #8
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#7
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#7
;Assume Bit Clear
;Send out bit #7
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#6
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#6
;Assume Bit Clear
;Send out bit #6
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#5
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#5
;Assume Bit Clear
;Send out bit #5
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
XL_PORT,#XL_DIN
W0,#4
;Assume Bit Clear
;Send out bit #4
162
bset
call
btsc
bset
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#4
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#3
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#3
;Assume Bit Clear
;Send out bit #3
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#2
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#2
;Assume Bit Clear
;Send out bit #2
;Bit Set
;Clock bit through
;Read in bit
;
bclr
btsc
bset
call
btsc
bset
XL_PORT,#XL_DIN
W0,#1
XL_PORT,#XL_DIN
Tilt_Clock_Pulse
XL_PORT,#XL_DOUT
W1,#1
;Assume Bit Clear
;Send out bit #1
;Bit Set
;Clock bit through
;Read in bit
;
bclr
XL_PORT,#XL_DIN
;Assume Bit Clear
btsc
W0,#0
;Send out bit #0
bset
XL_PORT,#XL_DIN
;Bit Set
call
Tilt_Clock_Pulse
;Clock bit through
btsc
XL_PORT,#XL_DOUT
;Read in bit
bset
W1,#0
;
return
;
;***********************************************
;*************************************************************
;********GPS Routines*****************************************
;*********************************************************
;gps_init - GPS Init Routine
;
;Initialize GPS pins
;*********************************************************
gps_init:
bclr
GPS_TRIS,#GPS_ENABLE
;
bclr
GPS_PORT,#GPS_ENABLE
;
clr
GPSFLAGS
;
clr
GPSBUF1CNT
;
clr
GPSBUF2CNT
;
return
;
;*********************************************************
;*********************************************************
;gps_enable - GPS Enable Routine
;
;Provides power to GPS module
;*********************************************************
gps_enable:
bset
GPS_PORT,#GPS_ENABLE
;
return
;
;*********************************************************
;*********************************************************
;gps_disable - GPS Disable Routine
163
;
;Removes power from GPS module
;*********************************************************
gps_disable:
bclr
GPS_PORT,#GPS_ENABLE
;
return
;
;*********************************************************
;*********************************************************
;gps_rxdata - GPS Recieve Data Byte Routine
;
;This routine looks for GPS messages and stores them to
;a buffer in RAM such that they can be stored.
;*********************************************************
gps_rxdata:
btsc
GPSFLAGS,#0
;Check if Message is in progress
goto
gps_rxdata_mip
;message in progress, deal with it
;no
message in progress
mov
#0x0024,W0
cp.b
U1RECEIVE
bra
Z,gps_rxdata_nm
return
;Check for start of new message ('$')
;
;Start of new message, write data
;not a new message, done
gps_rxdata_mip:
btsc
GPSFLAGS,#6
goto
gps_rxdata_mipw1
goto
gps_rxdata_mipw2
;Check which buffer is being used
;Buffer 1
;Buffer 2
gps_rxdata_nm:
btss
GPSFLAGS,#2
goto
gps_rxdata_w1
btss
GPSFLAGS,#4
goto
gps_rxdata_w2
bset
GPSFLAGS,#1
mov
#GPSBUFFULL,W2
mov
#22,W1
call
STRING_DISPLAY
mov
#0x0001,W1
call
NEWLINE_DISPLAY
return
gps_rxdata_w1:
bset
GPSFLAGS,#0
bset
GPSFLAGS,#6
clr
GPSBUF1CNT
gps_rxdata_mipw1:
mov
#GPSMSG1,W0
add
GPSBUF1CNT,WREG
mov
U1RECEIVE,W1
mov.b W1,[W0]
inc
GPSBUF1CNT
;Check for end of message
mov
#0x000A,W0
cp.b
U1RECEIVE
bra
Z,gps_rxdata_eom1
return
gps_rxdata_eom1:
bclr
GPSFLAGS,#0
bset
GPSFLAGS,#2
bset
GPSFLAGS,#3
return
gps_rxdata_w2:
;Check if buffer 1 is available
;yes it is, choose buffer 1
;Check if buffer 2 is available
;yes it is, choose buffer 2
;both buffers full, set error flag
;Send out error message
;"ERROR: GPS BUFFER FULL"
;
;New line
;
;return
;Set message in progress flag
;Set use buffer 1 flag
;clear byte counter
;load buffer address
;add byte count to buffer address
;
;place received character in next buffer location
;increment counter
;Check for end of message ('LF')
;
;End of message.. perform additional tasks
;not the end of the message, done
;Clear MIP Flag
;Set Buffer 1 Full Flag
;Set Buffer 1 Requires Writing Flag
;done
164
bset
GPSFLAGS,#0
;Set message in progress flag
bclr
GPSFLAGS,#6
;indicate use of buffer 2
clr
GPSBUF2CNT
;clear byte counter
gps_rxdata_mipw2:
mov
#GPSMSG2,W0
;load buffer address
add
GPSBUF2CNT,WREG
;add byte count to buffer address
mov
U1RECEIVE,W1
;
mov.b W1,[W0]
;place received character in next buffer location
inc
GPSBUF2CNT
;increment counter
;Check for end of message
mov
#0x000A,W0
;Check for end of message ('LF')
cp.b
U1RECEIVE
;
bra
Z,gps_rxdata_eom2
;End of message.. perform additional tasks
return
;not the end of the message, done
gps_rxdata_eom2:
bclr
GPSFLAGS,#0
;Clear MIP Flag
bset
GPSFLAGS,#4
;Set Buffer 2 Full Flag
bset
GPSFLAGS,#5
;Set Buffer 2 Requires Writing Flag
return
;done
;*********************************************************
;*********************************************************
;gps_rxdata_err
GPS Receive Data Error
;
;This routine is called when a GPS Data Receive Error
;occurs. It clears any pending message in progress so as
;to prevent incomplete data messages from being recorded.
;*********************************************************
gps_rxdata_err:
bclr
GPSFLAGS,#0
;Clear any message in progress
return
;
;*********************************************************
;*********************************************************
;gps_data_write
GPS Data Write
;
;This routine will check for any messeges in the two GPS
;RX Data Buffers. If there is a full message waiting to
;be written, it will write it.
;*********************************************************
gps_data_write:
bclr
GPSFLAGS,#7
;Clear GPS Data Written Flag
nop
btsc
GPSFLAGS,#3
;Check if buffer 1 requires writing
goto
gps_data_write_1
;yes it does, must check first for 2 messages
btsc
call
GPSFLAGS,#5
gps_data_write2
btss
GPSFLAGS,#7
call
gps_empty_write
return
gps_data_write_1:
btsc
GPSFLAGS,#5
goto
gps_data_write_2
no message
call
gps_data_write1
return
gps_data_write_2:
bclr
GPSFLAGS,#2
nop
bclr
GPSFLAGS,#3
nop
;Check if buffer 2 requires writing
;yes it does, write it
;Check if some GPS data written?
;no, write empty record
;All buffers written if needed, done
;Check if buffer 2 contains a message
;yes, two messages in buffer.. clear buffer, write
;no, write buffer 1 record
;clear "buffer full" flag
;clear "buffer requires writing" flag
165
bclr
GPSFLAGS,#4
;clear "buffer full" flag
nop
bclr
GPSFLAGS,#5
;clear "buffer requires writing" flag
call
gps_empty_write
;write empty record
return
;
;*********************************************************
;*********************************************************
;gps_data_write1
GPS WRITE BUFFER 1 DATA
;
;Writes out data in GPS RX Data 1 Buffer to SD Card.
;Assumes GPSBUF1CNT number of bytes in message beginning
;at GPS1BUFF memory location.
;*********************************************************
gps_data_write1:
bset
GPSFLAGS,#7
;Indicate GPS Data Written
mov
#GPSMSG1,W2
;load buffer address
mov
GPSBUF1CNT,W1
;load number of characters
dec
W1,W1
;rid of <CR> <LF>
dec
W1,W1
;
gps_data_write1l:
cp0
W1
;Check if there are still
bra
NZ,gps_data_write1so ;characters left to send
bra
gps_data_write1end
;no
gps_data_write1so:
;Characters left to send out
mov.b
[W2++],W0
;Send character out UART2 to datalogger
call
U2_Transmit
;
dec
W1,W1
;
bra
gps_data_write1l
;
gps_data_write1end:
bclr
GPSFLAGS,#2
;clear "buffer full" flag
nop
bclr
GPSFLAGS,#3
;clear "buffer requires writing" flag
return
;
;*********************************************************
;*********************************************************
;gps_data_write2
GPS WRITE BUFFER 2 DATA
;
;Writes out data in GPS RX Data 2 Buffer to SD Card.
;Assumes GPSBUF2CNT number of bytes in message beginning
;at GPS2BUFF memory location.
;*********************************************************
gps_data_write2:
bset
GPSFLAGS,#7
;Indicate GPS Data Written
mov
#GPSMSG2,W2
;load buffer address
mov
GPSBUF2CNT,W1
;load number of characters
dec
W1,W1
;rid of <CR> <LF>
dec
W1,W1
;
gps_data_write2l:
cp0
W1
;Check if there are still
bra
NZ,gps_data_write2so ;characters left to send
bra
gps_data_write2end
;no
gps_data_write2so:
;Characters left to send out
mov.b
[W2++],W0
;Send character out UART2 to datalogger
call
U2_Transmit
;
dec
W1,W1
;
bra
gps_data_write2l
;
gps_data_write2end:
bclr
GPSFLAGS,#4
;clear "buffer full" flag
nop
bclr
GPSFLAGS,#5
;clear "buffer requires writing" flag
return
;
166
;*********************************************************
;*********************************************************
;gps_empty_write
GPS EMPTY RECORD WRITE
;
;Writes an empty gps record to UART2
;*********************************************************
gps_empty_write:
mov
#14,W1
;load number comma, spaces
gps_empty_writel:
cp0
W1
;Check if there are still
bra
NZ,gps_empty_writeso ;characters left to send
bra
gps_empty_writeend
;no
gps_empty_writeso:
;Characters left to send out
mov
#0x002C,W0
;', ' (Comma,Space)
call
U2_Transmit
;
mov
#0x0020,W0
;
call
U2_Transmit
;
dec
W1,W1
;
bra
gps_empty_writel
;
gps_empty_writeend:
return
;
;*********************************************************
;*************************************************************
;********UART 1 ROUTINES**************************************
;****UART 1 Initialization***********************
UART1_Init:
;Make sure module isn't disabled
bclr
PMD1,#U1MD
;Enable UART1
;Setup UART Regisiters
mov
#BAUD_NUM1,W0
;Setup Bard Rate
mov
W0,U1BRG
;
mov
#U1STA_C,W0
;Setup interrupts, etc
mov
W0,U1STA
;
mov
#U1MODE_C,W0
;Setup Baud rate High Reg, etc
mov
W0,U1MODE
;
bset
U1STA,#UTXEN
;set transmit enabled
;Setup UART Interrupts
bset
INTCON1,#NSTDIS
;Disable Interrupt Nesting
bclr
IFS0,#U1RXIF
;Clear Recieve Interrupt Flag
bset
IEC0,#U1RXIE
;Enable Recieve Interrupt
return
;done
;************************************************
;*****UART 1 Transmit Routine********************
U1_Transmit:
bset
U1STA,#UTXEN
;set transmit enabled
mov
W0,U1TXREG
;send out W0
U1_TransWait:
nop
btsc
U1STA,#UTXBF
;Check if transmit buffer is full
goto
U1_TransWait
;buffer full, wait
return
;buffer has room for more, return
;************************************************
;*****UART 1 Disable Transmit Routine************
U1_TransmitDisable:
btss
U1STA,#TRMT
;Check that last byte has been sent out
goto
U1_TransmitDisable
;no, wait
bclr
U1STA,#UTXEN
;last byte out, disable transmit
return
;
;************************************************
167
;*****UART 1 Recieve Interrupt Routine***********
__U1RXInterrupt:
;Save context
push
W0
;Save W0
push
W1
;Save W1
push
W2
;
btsc
goto
U1STA,#OERR
U1OverrunError
;Check for overrun error
;overrun error occurred
btsc
goto
U1STA,#FERR
U1FramingError
;Check for framing error
;framing error detected
U1ReadByte:
;Byte(s) are ready to be read
mov
U1RXREG,W0
;
mov
W0,U1RECEIVE
;
;Call function to deal with recieved byte
btsc
MAIN_FLAGS,#6
;Check for GPS COM MODE
call
bt_transmit
;GPS COM MODE (send GPS data to computer)
btsc
MAIN_FLAGS,#7
;Check for GPS Data Storage Mode
call
gps_rxdata
;GPS DATA STORAGE MODE
;Byte has been dealt with
btsc
U1STA,#URXDA
;Check if another byte is available
goto
U1ReadByte
;yes, read it
;Restore context
pop
W2
pop
W1
pop
W0
bclr
IFS0,#U1RXIF
retfie
U1OverrunError:
mov
#U1ORERR,W2
mov
#11,W1
call
STRING_DISPLAY
mov
#0x0001,W1
call
NEWLINE_DISPLAY
call
gps_rxdata_err
;Restore context
pop
W2
pop
W1
pop
W0
bclr
U1STA,#OERR
bclr
IFS0,#U1RXIF
retfie
U1FramingError:
mov
#U1FRERR,W2
mov
#11,W1
call
STRING_DISPLAY
mov
#0x0001,W1
call
NEWLINE_DISPLAY
call
gps_rxdata_err
;Restore context
pop
W2
pop
W1
pop
W0
bclr
U1STA,#FERR
;
;Restore W1
;Restore W0
;Clear Recieve Interrupt Flag
;return
;Send out error message
;
;
;New line
;
;Clear MIP
;
;Restore W1
;Restore W0
;Clear error
;Clear Recieve Interrupt Flag
;
;Send out error message
;
;
;New line
;
;Clear MIP
;
;Restore W1
;Restore W0
;Clear error
168
bclr
IFS0,#U1RXIF
;Clear Recieve Interrupt Flag
retfie
;
;************************************************
;*************************************************************
;********Datalogger Routines**********************************
;*********************************************************
;data_init - Datalogger Init Routine
;
;Initializes all the datalogger pins
;*********************************************************
data_init:
bclr
DL_TRIS,#DL_ENABLE
;Datalogger disabled
bclr
DL_PORT,#DL_ENABLE
;
bclr
DL_TRIS,#DL_STOP
;Stop pin
bclr
DL_PORT,#DL_STOP
;
bclr
DL_TRIS,#DL_RST
;Reset pin
bclr
DL_PORT,#DL_RST
;
return
;
;*********************************************************
;*********************************************************
;data_enable - Datalogger Enable Routine
;
;Provides power to Datalogger module
;*********************************************************
data_enable:
bclr
DL_TRIS,#DL_ENABLE
;
bset
DL_PORT,#DL_ENABLE
;
return
;
;*********************************************************
;*********************************************************
;data_disable - Datalogger Disable Routine
;
;Removes power to Datalogger module
;*********************************************************
data_disable:
bclr
DL_TRIS,#DL_ENABLE
;
bclr
DL_PORT,#DL_ENABLE
;
return
;
;*********************************************************
;*********************************************************
;data_stop - Datalogger Stop Routine
;
;Stops logging data
;*********************************************************
data_stop:
bset
DL_PORT,#DL_STOP
;
call
delay100ms
;
bclr
DL_PORT,#DL_STOP
;
return
;
;*********************************************************
;*********************************************************
;data_reset - Datalogger Reset Routine
;
;Resets the datalogger to reenable data logging
;*********************************************************
data_reset:
bset
DL_PORT,#DL_RST
;
call
delay100ms
;
169
bclr
DL_PORT,#DL_RST
;
return
;
;*********************************************************
;*********************************************************
;data_trans - Datalogger Simple Transmit Routine
;
;Selects data logger, then sends byte in W0 out
;*********************************************************
data_trans:
bclr
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
;
bclr
U2SS_PORT,#TXSS1
;the Datalogger RX
call
U2_Transmit
;
return
;
;*********************************************************
;*********************************************************
;data_settx - Set Datalogger as TX device
;
;Selects data logger as TX device
;*********************************************************
data_settx:
bclr
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
;
bclr
U2SS_PORT,#TXSS1
;the Datalogger RX
return
;
;*********************************************************
;*********************************************************
;data_transmit - Datalogger Transmit Routine
;
;Sends value in W0 out to the datalogger
;*********************************************************
data_transmit:
push
SR
;Save Current status register
push
W1
;
mov
#0x00E0,W1
;Disable Interrupts
mov
W1,SR
;
btss
U2FLAGS,#1
;Last byte sent out to datalogger?
goto
data_transmit_set
;no, reset multiplexor
call
U2_Transmit
;yes, send byte out
bset
U2FLAGS,#1
;Indicate byte sent to datalogger
pop
W1
;
pop
SR
;Restore SR, enable interrupts
return
;
data_transmit_set:
btss
U2STA,#TRMT
;Byte still being transmitted?
goto
data_transmit_set
;yes, wait for completion
;all previous bytes transmitted
bset
U2FLAGS,#1
;Indicate byte sent to datalogger
bclr
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
bclr
U2SS_PORT,#TXSS1
;the Datalogger RX
nop
;
call
U2_Transmit
;
pop
W1
;
pop
SR
;Restore SR, enable interrupts
return
;
;*********************************************************
;*************************************************************
170
;********Conversion Routines**********************************
;*********************************************************
;SNUM2ASCII - Signed Number to ASCII
;Converts Signed 16-bit value in W0 to 5 ASCII characters plus
;a sign character.
;The ASCII values are stored in
;W6 - Sign (' ' or '-')
;W5 - ten thousands
;W4 - thousands
;W3 - hundreds
;W2 - tens
;W1 - ones
;*********************************************************
snum2ascii:
btss
W0,#15
;Check the sign bit
goto
snum2asciipos
;Positive Number
;negative number, must reverse the
;2's complement procedure before calling num2bcd
mov
#0xFFFF,W6
;Invert all the bits
xor
W0,W6,W0
;
inc
W0,W0
;add 1
call
num2bcd
;
mov
#0x002D,W6
;Set Sign character
add
#0x30,W1
;Convert BCD to ASCII
add
#0x30,W2
;
add
#0x30,W3
;
add
#0x30,W4
;
add
#0x30,W5
;
return
;
snum2asciipos:
mov
#0x0020,W6
;Set Sign character
call
num2bcd
;Convert digits
add
#0x30,W1
;Convert BCD to ASCII
add
#0x30,W2
;
add
#0x30,W3
;
add
#0x30,W4
;
add
#0x30,W5
;
return
;
;***********************************************
;*********************************************************
;NUM2ASCII - Number to ASCII
;Converts 16-bit value in W0 to 5 ASCII characters
;The BCD values are stored in
;W5 - ten thousands
;W4 - thousands
;W3 - hundreds
;W2 - tens
;W1 - ones
;*********************************************************
num2ascii:
call
num2bcd
;convert to BCD
add
#0x30,W1
;Convert BCD to ASCII
add
#0x30,W2
;
add
#0x30,W3
;
add
#0x30,W4
;
add
#0x30,W5
;
return
;
;*********************************************************
;*********************************************************
;NUM2BCD - Number to BCD
;Converts 16-bit value in W0 to 5 BCD digits
;The BCD values are stored in
171
;W5 - ten thousands
;W4 - thousands
;W3 - hundreds
;W2 - tens
;W1 - ones
;*********************************************************
num2bcd:
clr
W5
;Clear the variables to be stored
clr
W4
;
clr
W3
;
clr
W2
;
clr
W1
;
tenthoutest:
mov
#0x2710,W1
cp
W0,W1
bra
ltu,thoutest
sub
inc.b
bra
thoutest:
mov
cp
bra
sub
inc.b
bra
hundtest:
mov
cp
bra
sub
inc.b
bra
tentest:
mov
cp
bra
sub
inc.b
bra
W0,W1,W0
W5,W5
tenthoutest
#0x03E8,W1
W0,W1
ltu,hundtest
W0,W1,W0
W4,W4
thoutest
#0x0064,W1
W0,W1
ltu,tentest
W0,W1,W0
W3,W3
hundtest
#0x000A,W1
W0,W1
ltu,onetest
W0,W1,W0
W2,W2
tentest
;(10,000 in hex)
;
;Check if W0 >= 10,000
;it is
;Subtract 10,000 from Incoming number
;Increment BCD digit
;repeat
;(1,000 in hex)
;
;Check if W0 >= 1,000
;it is
;Subtract 1,000 from Incoming number
;Increment BCD digit
;repeat
;(100 in hex)
;
;Check if W0 >= 100
;it is
;Subtract 100 from Incoming number
;Increment BCD digit
;repeat
;(10 in hex)
;
;Check if W0 >= 10
;it is
;Subtract 10 from Incoming number
;Increment BCD digit
;repeat
onetest:
;Rest are ones currently stored in W0
mov
W0,W1
;
return
;***********************************************
;done
;*********************************************************
;BNUM2ASCII - Big Number to ASCII Character Array
;Converts 32-bit value in W1,W0 to 10 ASCII digits
;The ASCII values are stored in
;W10 - billions
;W9 - hundred millions
;W8 - ten millions
;W7 - millions
172
;W6 - hundred thousands
;W5 - ten thousands
;W4 - thousands
;W3 - hundreds
;W2 - tens
;W1 - ones
;*********************************************************
bnum2ascii:
clr
W10
;Clear the variables to be stored
clr
W9
;
clr
W8
;
clr
W7
;
clr
W6
;
clr
W5
;
clr
W4
;
clr
W3
;
clr
W2
;
clr
ACCAU
mov
W1,ACCAH
mov
W0,ACCAL
bbilliontest:
mov
#0x3B9A,W0
mov
W0,ACCBH
mov
#0xCA00,W0
mov
W0,ACCBL
;Check if ACCA is > than ACCB
mov
ACCAH,W0
mov
ACCBH,W1
cp
W0,W1
bra
ltu,bhundmilltest
bra
gtu,bbilliongt
mov
ACCAL,W0
mov
ACCBL,W1
cp
W0,W1
bra
ltu,bhundmilltest
bbilliongt:
SUB
A
inc.b
W10,W10
bra
bbilliontest
bhundmilltest:
mov
#0x05F5,W0
mov
W0,ACCBH
mov
#0xE100,W0
mov
W0,ACCBL
;Check if ACCA is > than ACCB
mov
ACCAH,W0
mov
ACCBH,W1
cp
W0,W1
bra
ltu,btenmilltest
bra
gtu,bhundmillgt
mov
ACCAL,W0
mov
ACCBL,W1
cp
W0,W1
bra
ltu,btenmilltest
bhundmillgt:
SUB
A
inc.b
W9,W9
bra
bhundmilltest
;Move 32-bit value to Accumulator
;
;
;(1,000,000,000 in hex)
;
;
;
;;First Check if ACCAH >= ACCBH
;
;
;no, no billions
;definetly some billions
;ACCAH = ACCBH
;Check LSBs
;
;no billions
;Subtract a billion from incoming number
;increment BCD digit
;repeat
;(100,000,000 in hex)
;
;
;
;;First Check if ACCAH >= ACCBH
;
;
;no, no hundred millions
;definetly some hundred millions
;ACCAH = ACCBH
;Check LSBs
;
;no hundred millions
;Subtract a hundred million from incoming number
;increment BCD digit
;repeat
173
btenmilltest:
mov
#0x0098,W0
mov
W0,ACCBH
mov
#0x9680,W0
mov
W0,ACCBL
;Check if ACCA is > than ACCB
mov
ACCAH,W0
mov
ACCBH,W1
cp
W0,W1
bra
ltu,bmilltest
bra
gtu,btenmillgt
mov
ACCAL,W0
mov
ACCBL,W1
cp
W0,W1
bra
ltu,bmilltest
btenmillgt:
SUB
A
inc.b
W8,W8
bra
btenmilltest
bmilltest:
mov
mov
mov
mov
#0x000F,W0
W0,ACCBH
#0x4240,W0
W0,ACCBL
;Check if ACCA is > than ACCB
mov
ACCAH,W0
mov
ACCBH,W1
cp
W0,W1
bra
ltu,bhundthoutest
bra
gtu,bmillgt
mov
ACCAL,W0
mov
ACCBL,W1
cp
W0,W1
bra
ltu,bhundthoutest
bmillgt:
SUB
A
inc.b
W7,W7
bra
bmilltest
bhundthoutest:
mov
#0x0001,W0
mov
W0,ACCBH
mov
#0x86A0,W0
mov
W0,ACCBL
;Check if ACCA is > than ACCB
mov
ACCAH,W0
mov
ACCBH,W1
cp
W0,W1
bra
ltu,btenthoutest
bra
gtu,bhundthougt
mov
ACCAL,W0
mov
ACCBL,W1
cp
W0,W1
bra
ltu,btenthoutest
bhundthougt:
SUB
A
inc.b
W6,W6
bra
bhundthoutest
;(10,000,000 in hex)
;
;
;
;;First Check if ACCAH >= ACCBH
;
;
;no, no ten millions
;definetly some ten millions
;ACCAH = ACCBH
;Check LSBs
;
;no tens of millions
;Subtract ten million from incoming number
;increment BCD digit
;repeat
;(1,000,000 in hex)
;
;
;
;;First Check if ACCAH >= ACCBH
;
;
;no, no millions
;definetly some millions
;ACCAH = ACCBH
;Check LSBs
;
;no millions
;Subtract a million from incoming number
;increment BCD digit
;repeat
;(100,000 in hex)
;
;
;
;;First Check if ACCAH >= ACCBH
;
;
;no, no hundred thousands
;definetly some hundred thousands
;ACCAH = ACCBH
;Check LSBs
;
;no hundred thousands
;Subtract a million from incoming number
;increment BCD digit
;repeat
174
btenthoutest:
mov
#0x0000,W0
mov
W0,ACCBH
mov
#0x2710,W0
mov
W0,ACCBL
;Check if ACCA is > than ACCB
mov
ACCAH,W0
mov
ACCBH,W1
cp
W0,W1
bra
ltu,bthoutestr
bra
gtu,btenthougt
mov
ACCAL,W0
mov
ACCBL,W1
cp
W0,W1
bra
ltu,bthoutestr
btenthougt:
SUB
A
inc.b
W5,W5
bra
btenthoutest
bthoutestr:
mov
ACCAL,W0
bthoutest:
mov
#0x03E8,W1
cp
W0,W1
bra
ltu,bhundtest
sub
inc.b
bra
W0,W1,W0
W4,W4
bthoutest
bhundtest:
mov
#0x0064,W1
cp
W0,W1
bra
ltu,btentest
sub
inc.b
bra
btentest:
mov
cp
bra
sub
inc.b
bra
W0,W1,W0
W3,W3
bhundtest
#0x000A,W1
W0,W1
ltu,bonetest
W0,W1,W0
W2,W2
btentest
;(10,000 in hex)
;
;
;
;;First Check if ACCAH >= ACCBH
;
;
;no, no ten thousands
;definetly some ten thousands
;ACCAH = ACCBH
;Check LSBs
;
;no tens of thousands
;Subtract a million from incoming number
;increment BCD digit
;repeat
;No need for a 32-bit accumulator anymore
;(1,000 in hex)
;
;Check if W0 >= 1,000
;it is
;Subtract 1,000 from Incoming number
;Increment BCD digit
;repeat
;(100 in hex)
;
;Check if W0 >= 100
;it is
;Subtract 100 from Incoming number
;Increment BCD digit
;repeat
;(10 in hex)
;
;Check if W0 >= 10
;it is
;Subtract 10 from Incoming number
;Increment BCD digit
;repeat
bonetest:
;Rest are ones currently stored in W0
mov
W0,W1
;
add
add
add
add
add
add
add
add
add
#0x30,W1
#0x30,W2
#0x30,W3
#0x30,W4
#0x30,W5
#0x30,W6
#0x30,W7
#0x30,W8
#0x30,W9
;Convert BCD to ASCII
;
;
;
;
;
;
;
;
175
add
#0x30,W10
;
return
;done
;***********************************************
;*************************************************************
;********Magnetometer ROUTINES********************************
;****Magnetometer Init**************************
Magnetometer_Init:
;Setup Pins as required
;SSbar
bclr
MSSTRIS,#MSSPIN
;SSbar an output
bset
MSSPORT,#MSSPIN
;SSbar high
;Reset
bclr
MRESTRIS,#MRESPIN
;Reset an output
bclr
MRESPORT,#MRESPIN
;Reset low
;SCLK
bclr
MSCLKTRIS,#MSCLKPIN ;SCLK an output
bclr
MSCLKPORT,#MSCLKPIN ;SCLK low
;MOSI
bclr
MMOSITRIS,#MMOSIPIN ;MOSI an output
bclr
MMOSIPORT,#MMOSIPIN ;MOSI low
;MISO
bset
MMISOTRIS,#MMISOPIN ;MISO an input
nop
;
;DRDY
bset
MDRDYTRIS,#MDRDYPIN ;DRDY an input
clr
XMAG
;Clear storage variables
clr
YMAG
;
clr
ZMAG
;
return
;done with init
;***********************************************
;*********************************************************
;Mag_Read_XYZ - Read all Magnetometer axes
;
;Reads all axes of magnetometer data and stores the results
;in XMAG,YMAG, and ZMAG respectively.
;*********************************************************
Mag_Read_XYZ:
mov
#0x0061,W0
;X-Axis
call
Magnetometer_Read
;Get Reading
mov
W0,XMAG
;Store Reading
mov
call
mov
#0x0062,W0
Magnetometer_Read
W0,YMAG
;Y-Axis
;Get Reading
;Store Reading
mov
call
mov
#0x0063,W0
Magnetometer_Read
W0,ZMAG
;Z-Axis
;Get Reading
;Store Reading
return
;*********************************************************
;****Magnetometer Read**************************
;W0 includes COMMAND BYTE (choose axis)
Magnetometer_Read:
bclr
MSSPORT,#MSSPIN
;SSbar low
nop
;
nop
;
bset
MRESPORT,#MRESPIN
;Reset line high
nop
;
nop
;
nop
;
bclr
MRESPORT,#MRESPIN
;Reset line low
176
nop
;
nop
;
;W0 should have COMMAND BYTE
call
Mag_Shift_Out
;Shift out Command Byte
Mag_wait:
btss
MDRDYPORT,#MDRDYPIN ;Wait till Data is Ready
goto
Mag_wait
;
;Data Ready, Shift in 16 bits
clr
W0
;All bits clear to start
call
Mag_Shift_In
;shift in highest 8 bits
swap
W0
;swap low for high byte
call
Mag_Shift_In
;shift in lowest 8 bits
bset
MSSPORT,#MSSPIN
;SSbar high
return
;***********************************************
;****Magnetometer Clock Pulse*******************
Mag_Clock_Pulse:
bset
MSCLKPORT,#MSCLKPIN ;Clock Pin High
nop
;
nop
;
nop
;
nop
;
bclr
MSCLKPORT,#MSCLKPIN ;Clock Pin Low
return
;
;***********************************************
;****Magnetometer Shift In**********************
Mag_Shift_In:
;Low byte of W0 assumed clear
btsc
MMISOPORT,#MMISOPIN ;Read in MSB
bset
W0,#7
;
call
Mag_Clock_Pulse
;Clock bit through
nop
btsc
bset
call
;
MMISOPORT,#MMISOPIN ;Read in #6
W0,#6
;
Mag_Clock_Pulse
;Clock bit through
nop
btsc
bset
call
;
MMISOPORT,#MMISOPIN ;Read in #5
W0,#5
;
Mag_Clock_Pulse
;Clock bit through
nop
btsc
bset
call
;
MMISOPORT,#MMISOPIN ;Read in #4
W0,#4
;
Mag_Clock_Pulse
;Clock bit through
nop
btsc
bset
call
;
MMISOPORT,#MMISOPIN ;Read in #3
W0,#3
;
Mag_Clock_Pulse
;Clock bit through
nop
btsc
bset
call
;
MMISOPORT,#MMISOPIN ;Read in #2
W0,#2
;
Mag_Clock_Pulse
;Clock bit through
nop
btsc
;
MMISOPORT,#MMISOPIN ;Read in #1
177
bset
call
W0,#1
Mag_Clock_Pulse
;
;Clock bit through
nop
;
btsc
MMISOPORT,#MMISOPIN ;Read in #0
bset
W0,#0
;
call
Mag_Clock_Pulse
;Clock bit through
return
;
;***********************************************
;****Magnetometer Shift Out*********************
Mag_Shift_Out:
bclr
MMOSIPORT,#MMOSIPIN ;Assume Bit Clear
btsc
W0,#7
;Send out MSB (#7)
bset
MMOSIPORT,#MMOSIPIN ;Bit Set
call
Mag_Clock_Pulse
;Clock bit through
bclr
btsc
bset
call
MMOSIPORT,#MMOSIPIN
W0,#6
MMOSIPORT,#MMOSIPIN
Mag_Clock_Pulse
;Assume Bit Clear
;Send out MSB (#6)
;Bit Set
;Clock bit through
bclr
btsc
bset
call
MMOSIPORT,#MMOSIPIN
W0,#5
MMOSIPORT,#MMOSIPIN
Mag_Clock_Pulse
;Assume Bit Clear
;Send out MSB (#5)
;Bit Set
;Clock bit through
bclr
btsc
bset
call
MMOSIPORT,#MMOSIPIN
W0,#4
MMOSIPORT,#MMOSIPIN
Mag_Clock_Pulse
;Assume Bit Clear
;Send out MSB (#4)
;Bit Set
;Clock bit through
bclr
btsc
bset
call
MMOSIPORT,#MMOSIPIN
W0,#3
MMOSIPORT,#MMOSIPIN
Mag_Clock_Pulse
;Assume Bit Clear
;Send out MSB (#3)
;Bit Set
;Clock bit through
bclr
btsc
bset
call
MMOSIPORT,#MMOSIPIN
W0,#2
MMOSIPORT,#MMOSIPIN
Mag_Clock_Pulse
;Assume Bit Clear
;Send out MSB (#2)
;Bit Set
;Clock bit through
bclr
btsc
bset
call
MMOSIPORT,#MMOSIPIN
W0,#1
MMOSIPORT,#MMOSIPIN
Mag_Clock_Pulse
;Assume Bit Clear
;Send out MSB (#1)
;Bit Set
;Clock bit through
bclr
btsc
bset
call
MMOSIPORT,#MMOSIPIN
W0,#0
MMOSIPORT,#MMOSIPIN
Mag_Clock_Pulse
;Assume Bit Clear
;Send out MSB (#0)
;Bit Set
;Clock bit through
return
;
;***********************************************
;*************************************************************
;********UART 2 ROUTINES**************************************
;****UART 2 Initialization***********************
UART2_Init:
;Make sure module isn't disabled
bclr
PMD1,#U2MD
;Enable UART2
;Setup the port pins
178
;Setup UART Regisiters
mov
#BAUD_NUM2,W0
mov
W0,U2BRG
mov
#U2STA_C,W0
mov
W0,U2STA
mov
#U2MODE_C,W0
mov
W0,U2MODE
bset
U2STA,#UTXEN
;Setup Baud Rate
;
;Setup interrupts, etc
;
;Setup Baud rate High Reg, etc
;
;set transmit enabled
;Setup UART Interrupts
bset
INTCON1,#NSTDIS
;Disable Interrupt Nesting
bclr
IFS1,#U2RXIF
;Clear Recieve Interrupt Flag
bset
IEC1,#U2RXIE
;Enable Recieve Interrupt
return
;done
;************************************************
;*****Computer Transmit Routine******************
computer_transmit:
push
SR
;Save Current status register
push
W1
;
mov
#0x00E0,W1
;Disable Interrupts
mov
W1,SR
;
btsc
U2FLAGS,#1
;Last byte sent out to computer?
goto
computer_transmit_set ;no, reset multiplexor
call
bt_transmit_check
;yes, send byte out
call
U2_Transmit
;still have to select bt or rs-232 though
bclr
U2FLAGS,#1
;Indicate byte sent to computer
pop
W1
;
pop
SR
;Restore SR, enable interrupts
return
;
computer_transmit_set:
btss
U2STA,#TRMT
;Byte still being transmitted?
goto
computer_transmit_set ;yes, wait for completion
;all previous bytes transmitted
bclr
U2FLAGS,#1
;Indicate byte sent to computer
call
bt_transmit_check
;Select Bluetooth or RS-232
call
U2_Transmit
;
pop
W1
;
pop
SR
;Restore SR, enable interrupts
return
;
;************************************************
;*****UART 2 Transmit Routine********************
U2_Transmit:
bset
U2STA,#UTXEN
;set transmit enabled
mov
W0,U2TXREG
;send out W0
U2_TransWait:
nop
btsc
U2STA,#UTXBF
;Check if transmit buffer is full
goto
U2_TransWait
;buffer full, wait
return
;buffer has room for more, return
;************************************************
;*****UART 2 Disable Transmit Routine************
U2_TransmitDisable:
btss
U2STA,#TRMT
;Check that last byte has been sent out
goto
U2_TransmitDisable
;no, wait
bclr
U2STA,#UTXEN
;last byte out, disable transmit
return
;
;************************************************
;*****UART 2 Recieve Interrupt Routine***********
__U2RXInterrupt:
;Save context
push
W0
;Save W0
179
push
push
W1
W2
;
;
btsc
goto
U2STA,#OERR
U2OverrunError
;Check for overrun error
;overrun error occurred
btsc
goto
U2STA,#FERR
U2FramingError
;Check for framing error
;framing error detected
clr
W0
U2ReadByte:
;Byte(s) are ready to be read
bclr
U2FLAGS,#0
mov
mov
add
U2RNUM,WREG
#U2RECEIVE,W1
W0,W1,W2
;Clear UART2 Interrupt Occurred? Flag
;Load Address Location
;
;
mov
mov.b
U2RXREG, W0
W0,[W2++]
;
;Save received word
btsc
call
btsc
call
btsc
MAIN_FLAGS,#6
U1_Transmit
MAIN_FLAGS,#5
bt_transmit
MAIN_FLAGS,#8
call
data_trans
;GPS COM MODE?
;yes, send character out to GPS unit
;Echo Character?
;yes
;Datalog Mode?
;(Logs all incoming characters to data logger)
;yes
inc
mov
cp
bra
U2RNUM
#30,W0
U2RNUM
GEU,u2rxint_clr
;Increment Received Word Count
;Check if byte count too high
;
;byte count >= 30, clear buffer
;Byte has been dealt with
btsc
U2STA,#URXDA
goto
U2ReadByte
;Check if another byte is available
;yes, read it
;Restore context
pop
W2
pop
W1
pop
W0
bclr
IFS1,#U2RXIF
retfie
;
;
;Restore W0
;Clear Recieve Interrupt Flag
;return
U2OverrunError:
mov
#U2ORERR,W2
mov
#11,W1
call
STRING_DISPLAY
mov
#0x0001,W1
call
NEWLINE_DISPLAY
pop
pop
pop
bclr
bclr
retfie
W2
W1
W0
U2STA,#OERR
IFS1,#U2RXIF
U2FramingError:
mov
#U2FRERR,W2
mov
#11,W1
;Send out error message
;
;
;New line
;
;
;
;Restore W0
;Clear error
;Clear Recieve Interrupt Flag
;
;Send out error message
;
180
call
mov
call
pop
pop
pop
bclr
bclr
retfie
STRING_DISPLAY
#0x0001,W1
NEWLINE_DISPLAY
W2
W1
W0
U2STA,#FERR
IFS1,#U2RXIF
;
;New line
;
;
;
;Restore W0
;Clear error
;Clear Recieve Interrupt Flag
;
u2rxint_clr:
clr
U2RNUM
;too many bytes, clear buffer
pop
W2
;
pop
W1
;
pop
W0
;Restore W0
bclr
IFS1,#U2RXIF
;Clear Recieve Interrupt Flag
retfie
;
;************************************************
;*************************************************************
;*********************************************************
;com_transmit - Computer Transmit Routine
;
;Sends value in W0 out to the Computer
;*********************************************************
com_transmit:
bclr
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
bset
U2SS_PORT,#TXSS1
;the Computer RX
call
U2_Transmit
;
return
;
;*********************************************************
;*********************************************************
;bt_transmit - Bluetooth Transmit Routine
;
;Sends value in W0 out via Bluetooth
;*********************************************************
bt_transmit:
bset
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
bclr
U2SS_PORT,#TXSS1
;the BT RX
call
U2_Transmit
;
return
;
;*********************************************************
;*********************************************************
;bt_settx - Set Bluetooth to TX Device
;
;Selects bluetooth as TX device
;*********************************************************
bt_settx:
bset
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
bclr
U2SS_PORT,#TXSS1
;the BT RX
return
;
;*********************************************************
;*********************************************************
;bt_receive - Bluetooth Receive Mode
;
;Forces UART 2 to recieve from the bluetooth module
;regardless of whether there is an active connection.
;*********************************************************
bt_receive:
bset
U2SS_PORT,#RXSS0
;Connect UART2 RX to the
;
181
nop
bclr
U2SS_PORT,#RXSS1
;Bluetooth TX
return
;
;*********************************************************
;*********************************************************
;bt_conn_check - Bluetooth Connection Check
;
;Forces UART 2 to recieve from the bluetooth module
;regardless of whether there is an active connection.
;*********************************************************
bt_conn_check:
btsc
INT_PORT,#BT_CONN
;Check for bluetooth connection
bset
MAIN_FLAGS,#9
;Bluetooth connected, set flag
btss
INT_PORT,#BT_CONN
;Check for bt connection
bclr
MAIN_FLAGS,#9
;Bluetooth not connected, clear flag
return
;
;*********************************************************
;********MAIN ROUTINES***************************************
;*********************************************************
;bt_receive_check - Bluetooth Receive Check
;
;Check whether bluetooth connection is active, if so set
;UART 2 to receive from the bluetooth module. If
;bluetooth is not active, set UART 2 to receive from the
;computer.
;*********************************************************
bt_receive_check:
btsc
INT_PORT,#BT_CONN
;Check for bluetooth connection
goto
bt_connected
;Bluetooth connected
bt_unconnected:
bclr
U2SS_PORT,#RXSS0
;Connect UART2 RX to the
nop
bset
U2SS_PORT,#RXSS1
;Computer TX
return
;
bt_connected:
bset
U2SS_PORT,#RXSS0
;Connect UART2 RX to the
nop
bclr
U2SS_PORT,#RXSS1
;Bluetooth TX
return
;
;*********************************************************
;*********************************************************
;bt_transmit_check - Bluetooth Transmit Check
;
;Check whether bluetooth connection is active, if so set
;UART 2 to transmit to the bluetooth module. If
;bluetooth is not active, set UART 2 to transmit to the
;computer.
;*********************************************************
bt_transmit_check:
btsc
INT_PORT,#BT_CONN
;Check for bluetooth connection
goto
btt_connected
;Bluetooth connected
btt_unconnected:
bclr
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
;
bset
U2SS_PORT,#TXSS1
;the Computer RX
return
;
btt_connected:
bset
U2SS_PORT,#TXSS0
;Connect UART2 TX to
nop
;
bclr
U2SS_PORT,#TXSS1
;the BT RX
return
;
182
;*********************************************************
;*********************************************************
;main_init - Main Init Routine
;
;Initializes all pins which wouldn't be initialized
;otherwise
;*********************************************************
main_init:
bclr
U2SS_TRIS,#RXSS0
;UART2 Source Select
nop
bclr
U2SS_TRIS,#RXSS1
;Pins Outputs
nop
bclr
U2SS_TRIS,#TXSS0
;
nop
bclr
U2SS_TRIS,#TXSS1
;
nop
bclr
U2SS_PORT,#RXSS0
;UART2 Default Source
nop
bset
U2SS_PORT,#RXSS1
;RX - COMPUTER
nop
bclr
U2SS_PORT,#TXSS0
;TX - COMPUTER
nop
bset
U2SS_PORT,#TXSS1
;
nop
bset
INT_TRIS,#GPS_INT
;GPS 1PPS, INPUT
nop
bset
INT_TRIS,#BT_CONN
;BT CONN, INPUT
return
;*********************************************************
;*************************************************************
;********DELAY ROUTINES***************************************
;*********************************************************
;delay1s ;
;Delays ~ 1 second
;*********************************************************
delay1s:
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
call
delay100ms
;
return
;*********************************************************
;*********************************************************
;delay100ms ;
;Delays 100ms
;*********************************************************
delay100ms:
mov
#20,W4
;delay ~100ms
delayloop100ms:
call
delay5ms
;
dec
W4,W4
;
bra
NZ,delayloop100ms
;
return
;
;
183
delay5ms:
mov
#40,W2
;load counter
delayloop:
call
delay125us
;delay 125us
dec
W2,W2
;Delayed 5ms?
bra
NZ,delayloop
;
return
;yep
;*********************************************************
;*********************************************************
;delay125us ;
;Delays 125us
;*********************************************************
delay125us:
mov
#0x014B,W3
;load counter (0x014B for Fcyl=8MHz)
delayloop2:
;
dec
W3,W3
;
bra
NZ,delayloop2
;Delayed 125us?
nop
nop
return
;yep
;*********************************************************
;*********************************************************
;delay71us ;
;Delays 71us
;*********************************************************
delay71us:
mov
#0x00BB,W3
;load counter (0x014B for Fcyl=8MHz)
delayloop271:
;
dec
W3,W3
;
bra
NZ,delayloop271
;Delayed 71us?
nop
nop
return
;yep
;*********************************************************
;*************************************************************
.end
184
;**********************************************************************************
;******************* ACOUSTIC PROCESSOR MICROCONTROLLER CODE **********************
;**********************************************************************************
.equ __33FJ128GP306, 1
.include "p33FJ128GP306.inc"
;..............................................................................
;Configuration bits:
;..............................................................................
config __FOSC, FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_EC
;Turn off clock
switching and
;fail-safe clock monitoring and
;use the External Clock as the
;system clock
config __FWDT, FWDTEN_OFF & WINDIS_OFF;Turn off Watchdog Timer
config __FPOR, FPWRT_PWR128
;Set Power on Timer 128 mSec
config __FOSCSEL, FNOSC_PRIPLL & IESO_OFF & TEMP_OFF ;Setup Oscillator
(w/PLL)
config __FGS, GSS_OFF & GCP_OFF & GWRP_OFF ;Disable Code protect
config __FSS, RSS_NO_RAM & SSS_NO_FLASH & SWRP_WRPROTECT_OFF ;No security
config __FBS, RBS_NO_RAM & BSS_NO_FLASH & BWRP_WRPROTECT_OFF ;
;..............................................................................
;Program Specific Constants (literals used in code)
;..............................................................................
;----ACOUSTIC PROCESSOR EQUATES------------------.equ
AP_PORT,PORTG
;
.equ
AP_TRIS,TRISG
;
.equ
AP_SS,9
;
.equ
AP_SDO,8
;
.equ
AP_SCK,6
;
.equ
AP_SDI,7
;
.equ
AP_APORT,PORTC
;
.equ
AP_AIO1,2
;
;----DIGITAL POTENTIOMETER EQUATES-------------.equ
DP_CPORT,PORTG
;Control Line Port
.equ
DP_CTRIS,TRISG
;
.equ
DP_CS_PRE,0
;
.equ
DP_CS_PST,14
;
.equ
DP_SCLK_PRE,12
;
.equ
DP_SCLK_PST,13
;
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
;----TRANSDUCER
.equ
.equ
DP_DPORT,PORTD
;Data Line Port
DP_DTRIS,TRISD
;
DP_DIN1_PRE,2
;Pre-Amp Digital Pot Line
DP_DIN1_PST,3
;Post-Amp Digital Pot Line
DP_DIN2_PRE,4
;Pre-Amp Digital Pot Line
DP_DIN2_PST,5
;Post-Amp Digital Pot Line
DP_DIN3_PRE,6
;Pre-Amp Digital Pot Line
DP_DIN3_PST,7
;Post-Amp Digital Pot Line
DRIVER EQUATES-----------------TDC_PORT,PORTD
;
TDC_TRIS,TRISD
;
185
.equ
.equ
TDC_PHASE,1
TDC_ENABLE,0
;
;
.equ
.equ
.equ
.equ
TDC_EPORT,PORTC
TDC_ETRIS,TRISC
TDC_MODE,14
TDC_NFLT,13
;
;
;
;
;----TONE DECODER EQUATES----------------------.equ
TD_PORT,PORTD
;
.equ
TD_TRIS,TRISD
;
.equ
TD_OUT1,8
;
.equ
TD_OUT2,9
;
.equ
TD_OUT3,10
;
;----ANALOG INPUT EQUATES----------------------.equ
AI_PORT,PORTB
;
.equ
AI_TRIS,TRISB
;
.equ
AI_PRE1,4
;
.equ
AI_POST1,0
;
.equ
AI_PRE2,1
;
.equ
AI_POST2,2
;
.equ
AI_PRE3,5
;
.equ
AI_POST3,3
;
;----LED EQUATES-------------------------------.equ
LED_PORT,PORTF
;
.equ
LED_TRIS,TRISF
;
.equ
LED1,6
;
.equ
LED2,2
;
.equ
LED3,3
;
;..............................................................................
;Global Declarations:
;..............................................................................
.global
.global
.global
;.global
__reset
__SPI2Interrupt
__SPI2ErrInterrupt
__T1Interrupt
;The label for the first line of code.
;
;
;Declare Timer 1 ISR name global
;..............................................................................
;Constants stored in Program space
;..............................................................................
;
.section .myconstbuffer, code
;
.palign 2
;Align next word stored in Program space to an
;
;address that is a multiple of 2
;ps_coeff:
;
.hword
0x0002, 0x0003, 0x0005, 0x000A
;..............................................................................
;Uninitialized variables
;..............................................................................
TEMP:
PRE1:
PRE2:
PRE3:
POST1:
POST2:
.section vars,bss,address(0x900)
.space 2
.space 2 ;default 0x00FF
.space 2 ;default 0x00FF
.space 2 ;default 0x00FF
.space 2 ;default 0x00FF
.space 2 ;default 0x00FF
186
POST3:
.space 2 ;default 0x00FF
BIGTOH:
.space 2 ;default 0x0131
BIGTOL:
.space 2 ;default 0x2D00
SMALLTOH:
.space 2 ;default 0x0000
SMALLTOL:
.space 2 ;default 0x4E20
TDC_DLYVAL: .space 2 ;default #145 = 45khz @ 40 MIPS
TDC_NUMCYC: .space 2 ;default #45 (1ms)
SPITRANSMIT: .space 20
SPIRECEIVE: .space 50
SPIRNUM:
.space 2
SPITNUM:
.space 2
SPIFLAGS:
.space 2
RANGETIMEH: .space 2
RANGETIMEL: .space 2
TRANSTIME1: .space 2
TRANSTIME2: .space 2
TRANSTIME3: .space 2
TRANSORDER: .space 2
;0,0,0 = No Returned Signal Timeout
;0,0,1 = 1,2,3
;0,1,0 = 1,3,2
;0,1,1 = 2,1,3
;1,0,0 = 2,3,1
;1,0,1 = 3,1,2
;1,1,0 = 3,2,1
;1,1,1 = Not All Returned Timeout
;..............................................................................
;Uninitialized variables in Y-space in data memory
;..............................................................................
;
;y_input:
.section .ybss, bss, ymemory
.space 2*SAMPLES
;..............................................................................
;Initialized variables in data memory
;..............................................................................
;..............................................................................
;Uninitialized variables in Near data memory (Lower 8Kb of RAM)
;..............................................................................
;
.section .nbss, bss, near
.section vars,bss,address(0x900)
;..............................................................................
;Code Section in Program Memory
;..............................................................................
.text
__reset:
mov #__SP_init, W15
mov #__SPLIM_init, W0
mov W0, SPLIM
nop
;Start of Code section
;Initalize the Stack Pointer
;Initialize the Stack Pointer Limit Register
;Add NOP to follow SPLIM initialization
main:
;Initialize PLL to proper frequency
;PLL will work on startup if 4mHz<Fin<8mHz
;(it was checked that PLL settings will within
;limits during this PLL update process)
mov
#0x0000,W0
;PLLPRE=2,PLLPOST=2 (for 40MIPS)
mov
W0,CLKDIV
;
187
mov
mov
#0x004E,W0
W0,PLLFBD
;Set PLL Multiplier=80 (for 40MIPS)
;
;Disable all modules
mov
#0xFFFF,W0
mov
W0,PMD1
mov
W0,PMD2
mov
W0,PMD3
;
;
;
;
;Disable all open-drains
mov
#0x0000,W0
mov
W0,ODCD
mov
W0,ODCF
mov
W0,ODCG
;
;Port D
;Port F
;Port G
;Disable Analog Function of I/O Pins
mov
#0xFFFF,W0
;
mov
W0,AD1PCFGH
;
mov
W0,AD1PCFGL
;
;Initialize
call
call
call
call
call
call
call
Everything
DP_INIT
TD_INIT
TDC_INIT
LED_INIT
Timer45_init
SPI_INIT
IC_INIT
;Initialize
;Initialize
;Initialize
;Initialize
;Initialize
;Initialize
;Initialize
Digital Potentiometers
Tone Decoder
Transducer Driver Circuit
LEDs
Timer
SPI
Input Capture
main_loop:
nop
bset
LED_PORT,#LED1
;
cp0
SPIRNUM
;Wait for a command to be received
bra
Z,main_loop
;
;Byte Received, Check for a command
bclr
LED_PORT,#LED1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov
#0X474D,W0
;'GM'
cp
SPIRECEIVE
;
bra
Z,GMCMD
;Get Measurement Command Received
mov
cp
bra
#0X4742,W0
SPIRECEIVE
Z,GBCMD
;'GB'
;
;Get Bearing Command Received
mov
cp
bra
#0X5352,W0
SPIRECEIVE
Z,SRCMD
;'SR'
;
;Send Reading Command Received
mov
cp
bra
#0X5152,W0
SPIRECEIVE
Z,QRCMD
;'QR'
;
;Quit Reading Command Received
mov
cp
bra
#0X5450,W0
SPIRECEIVE
Z,TPCMD
;'TP'
;
;Transmit Pulse Command Received
mov
cp
bra
#0X5350,W0
SPIRECEIVE
Z,SPCMD
;'SP'
;
;Set Parameters Command Received
188
mov
cp
bra
#0X5241,W0
SPIRECEIVE
Z,SPCMD
;'RA'
;
;Read ADC Command Received
;No recognized command received, clear it
clr
SPIRNUM
;
goto
main_loop
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GMCMD: ;GET MEASUREMENT COMMAND
bset
LED_PORT,#LED3
;
clr
RANGETIMEH
;Clear variables
clr
RANGETIMEL
;
clr
TRANSTIME1
;
clr
TRANSTIME2
;
clr
TRANSTIME3
;
clr
TRANSORDER
;
call
call
TDC_TOUT
IC_START
;Transmit Pulse, start big timeout
;Capture Ping
mov
#SPITRANSMIT,W2
;Formulate Message in memory
mov
mov
#0X474D,W0
W0,[W2++]
;1 'GM'
;
mov
mov
RANGETIMEH,W0
W0,[W2++]
;2
;
mov
mov
RANGETIMEL,W0
W0,[W2++]
;3
;
mov
mov
TRANSORDER,W0
W0,[W2++]
;4
;
mov
mov
TRANSTIME1,W0
W0,[W2++]
;5
;
mov
mov
TRANSTIME2,W0
W0,[W2++]
;6
;
mov
mov
TRANSTIME3,W0
W0,[W2++]
;7
;
mov
mov
#0x0007,W0
W0,SPITNUM
;
;
call
SPI_WRITE
;Send data out
bclr
LED_PORT,#LED3
;
clr
SPIRNUM
;clear byte count
goto
main_loop
;return to main loop
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GBCMD: ;GET BEARING COMMAND
bset
LED_PORT,#LED2
;
clr
TRANSTIME1
;
clr
TRANSTIME2
;
clr
TRANSTIME3
;
clr
TRANSORDER
;
bclr
bclr
T4CON,#15
IFS1,#T5IF
;Ensure timer is stopped
;Clear interrupt flag
call
IC_START
;
189
mov
#SPITRANSMIT,W2
;Formulate Message in memory
mov
mov
#0X4742,W0
W0,[W2++]
;1 'GB'
;
mov
mov
TRANSORDER,W0
W0,[W2++]
;4
;
mov
mov
TRANSTIME1,W0
W0,[W2++]
;5
;
mov
mov
TRANSTIME2,W0
W0,[W2++]
;6
;
mov
mov
TRANSTIME3,W0
W0,[W2++]
;7
;
mov
mov
#0x0005,W0
W0,SPITNUM
;
;
call
SPI_WRITE
;Send data out
clr
SPIRNUM
;clear byte count
bclr
LED_PORT,#LED2
;
goto
main_loop
;return to main loop
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SRCMD: ;Send Readings Command
nop
;Not yet implemented
clr
SPIRNUM
;clear byte count
goto
main_loop
;return to main loop
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
QRCMD: ;Quit Readings Command
nop
;not yet implemented
clr
SPIRNUM
;clear byte count
goto
main_loop
;return to main loop
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TPCMD: ;Transmit Pulse Command
mov
#0x0002,W0
;Check that at least 2 bytes are waiting
cp
SPIRNUM
;
bra
LTU,TPCMD
;not enough bytes yet, wait
;
;
;
;
;
mov
mov
#SPIRECEIVE,W2
[++W2],W0
;Retrieve Pulse length
;
mov
mov
call
mov
TDC_NUMCYC,W5
W0,TDC_NUMCYC
TDC_TOUT
W5,TDC_NUMCYC
;Store previous number of cycles
;replace cycle count with that from command
;send out requested pulse
;Restore cycle count
mov
mov
mov
mov
call
#0X5450,W0
W0,SPITRANSMIT
#0x0001,W0
W0,SPITNUM
SPI_WRITE
;Send out 'TP'
;
;
;
;Send data out
clr
SPIRNUM
;clear byte count
goto
main_loop
;return to main loop
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SPCMD: ;Set Parameters
mov
#0x000C,W0
;Check that at least 12 bytes are waiting
cp
SPIRNUM
;
bra
LTU,SPCMD
;not enough bytes yet, wait
190
;
;
;
;
;
mov
mov
mov
#SPIRECEIVE,W2
[++W2],W0
W0,TDC_NUMCYC
;
;Retrieve number of transmit cycles
;
mov
mov
[++W2],W0
W0,PRE1
;Retrieve Pre-Amp 1 Gain
;
mov
mov
[++W2],W0
W0,PRE2
;Retrieve Pre-Amp 2 Gain
;
mov
mov
[++W2],W0
W0,PRE3
;Retrieve Pre-Amp 3 Gain
;
mov
mov
[++W2],W0
W0,POST1
;Retrieve Post-Amp 1 Gain
;
mov
mov
[++W2],W0
W0,POST2
;Retrieve Post-Amp 2 Gain
;
mov
mov
[++W2],W0
W0,POST3
;Retrieve Post-Amp 3 Gain
;
mov
mov
[++W2],W0
W0,BIGTOH
;Retrieve Big Timeout High Word
;
mov
mov
[++W2],W0
W0,BIGTOL
;Retrieve Big Timeout Low Word
;
mov
mov
[++W2],W0
W0,SMALLTOH
;Retrieve Small Timeout High Word
;
mov
mov
[++W2],W0
W0,SMALLTOL
;Retrieve Small Timeout Low Word
;
mov
mov
mov
mov
call
#0X5350,W0
W0,SPITRANSMIT
#0x0001,W0
W0,SPITNUM
SPI_WRITE
;Send out 'SP'
;
;
;
;Send data out
clr
SPIRNUM
;clear byte count
mov
mov
mov
call
mov
mov
mov
call
PRE1,W0
PRE2,W1
PRE3,W2
DP_SET_PRE
POST1,W0
POST2,W1
POST3,W2
DP_SET_PST
;Set Pre-Amp Gain
;
;
;
;Set Post-Amp Gain
;
;
;
goto
main_loop
;return to main loop
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
RACMD: ;Read ADC Command
nop
;not yet implemented
clr
SPIRNUM
;clear byte count
goto
main_loop
;return to main loop
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
191
;********SPI Routines*****************************************
;*********************************************************
;SPI_INIT SPI Initialization
;*********************************************************
SPI_INIT:
clr
SPIRNUM
;Clear Counters
clr
SPITNUM
;
clr
SPIFLAGS
;Clear Flags
bclr
AP_TRIS,#AP_SS
;Use SS pin for telling master
;that data is ready
bclr
PMD1,#SPI2MD
;Make sure module isn't disabled
clr
SPI2BUF
;Clear SPIxBUF register
clr
SPI2STAT
;
;if using interrupts:
;
bclr
IFS2,#SPI2IF
;
nop
bclr
IFS2,#SPI2EIF
;
nop
;
bset
IEC2,#SPI2IE
;
nop
;
bset
IEC2,#SPI2EIE
;
bset
IPC8,#9
;Set Interrupt Priority 3
nop
;
bclr
IPC8,#10
;
nop
;
bset
IPC8,#8
;
mov
#0x0400,W0
;Setup 1st SPI Control Register
mov
W0,SPI2CON1
;Slave Mode
mov
#0x0000,W0
;Setup 2nd SPI Control Register
mov
W0,SPI2CON2
;No framed SPI support
bclr
SPI2CON1,#SMP
;Clear SMP bit
bclr
SPI2STAT,#SPIROV
;Clear SPIROV bit
nop
bset
SPI2STAT,#SPIEN
;Enable SPI Operation
return
;*********************************************************
;*********************************************************
;__SPI2Interrupt SPI Interrupt Routine
;*********************************************************
__SPI2Interrupt:
push
W0
;
push
W1
;
push
W2
;
bclr
bclr
IFS2,#SPI2IF
SPIFLAGS,#0
;Clear Interrupt Flag
;Clear SPI Interrupt Occurred? Flag
cp0
bra
SPITNUM
NZ,SPIINTTRANSMIT
;Check if any data to be transmitted
;
rlnc
mov
add
SPIRNUM,WREG
#SPIRECEIVE,W1
W0,W1,W2
;Load Address Location
;
;
mov
mov
SPI2BUF,W0
W0,[W2++]
;Retrieve word
;Save received word
inc
SPIRNUM
SPIINTRETURN:
pop
W2
pop
W1
pop
W0
;Increment Received Word Count
;
;
;
192
retfie
;
SPIINTTRANSMIT:
dec
SPITNUM
;decrement Transmit Counter
mov
SPI2BUF,W0
;Read data out to prevent overflow
cp0
SPITNUM
;Check if any more data to be transmitted
bra
Z,SPITRANSNOMORE
;
bset
AP_PORT,#AP_SS
;ensure data ready line is high
goto
SPIINTRETURN
;
SPITRANSNOMORE:
bclr
AP_PORT,#AP_SS
;
goto
SPIINTRETURN
;
;*********************************************************
;*********************************************************
;__SPI2ErrInterrupt SPI ERROR Interrupt
;
;If an SPI overflow occurs, overflow flag must be cleared
;to re-enable reception
;*********************************************************
__SPI2ErrInterrupt:
bclr
IFS2,#SPI2EIF
;Clear interrupt flag
bclr
SPI2STAT,#SPIROV
;Clear SPIROV bit
retfie
;
;*********************************************************
;*********************************************************
;SPI_WRITE SPI Word Write
;
;Data to be written is to be stored at location SPITRANSMIT
;Number of words to be written stored in SPITNUM
;*********************************************************
SPI_WRITE:
mov
#SPITRANSMIT,W2
;Load start address
SPI_REWRITE:
cp0
SPITNUM
;Check if any data to be transmitted
bra
NZ,SPI_WRITEWORD
;
return
;no data to send
SPI_WRITEWORD:
bset
SPIFLAGS,#0
;Set interrupt check flag
mov
[W2++],W0
;
mov
W0,SPI2BUF
;Send Received word out
bset
AP_PORT,#AP_SS
;Set data ready line
SPI_WRITE_WAIT:
btsc
SPIFLAGS,#0
;Transfer occur yet?
goto
SPI_WRITE_WAIT
;no
goto
SPI_REWRITE
;yes
;*********************************************************
;*************************************************************
;********Digital Potentiometer Routines***********************
;*********************************************************
;DP_INIT - Digital Potentiometer Initialization
;*********************************************************
DP_INIT:
bclr
DP_CTRIS,#DP_CS_PRE
;CS Output
bset
DP_CPORT,#DP_CS_PRE
;
bclr
DP_CTRIS,#DP_CS_PST
;CS Output
bset
DP_CPORT,#DP_CS_PST
;
bclr
bset
bclr
bset
DP_CTRIS,#DP_SCLK_PRE
DP_CPORT,#DP_SCLK_PRE
DP_CTRIS,#DP_SCLK_PST
DP_CPORT,#DP_SCLK_PST
;SCLK Output
;
;SCLK Output
;
193
bclr
bclr
bclr
bclr
DP_DTRIS,#DP_DIN1_PRE
DP_DPORT,#DP_DIN1_PRE
DP_DTRIS,#DP_DIN1_PST
DP_DPORT,#DP_DIN1_PST
;DIN Output
;
;DIN Output
;
bclr
bclr
bclr
bclr
DP_DTRIS,#DP_DIN2_PRE
DP_DPORT,#DP_DIN2_PRE
DP_DTRIS,#DP_DIN2_PST
DP_DPORT,#DP_DIN2_PST
;DIN Output
;
;DIN Output
;
bclr
bclr
bclr
bclr
DP_DTRIS,#DP_DIN3_PRE
DP_DPORT,#DP_DIN3_PRE
DP_DTRIS,#DP_DIN3_PST
DP_DPORT,#DP_DIN3_PST
;DIN Output
;
;DIN Output
;
mov
mov
mov
mov
mov
mov
mov
#0x00FF,W0
W0,PRE1
W0,PRE2
W0,PRE3
W0,POST1
W0,POST2
W0,POST3
;Set minimum gain to start
;
;
;
;
;
;
mov
PRE1,W0
;Set Pre-Amp Gain
mov
PRE2,W1
;
mov
PRE3,W2
;
call
DP_SET_PRE
;
mov
POST1,W0
;Set Post-Amp Gain
mov
POST2,W1
;
mov
POST3,W2
;
call
DP_SET_PST
;
return
;
;*********************************************************
;*********************************************************
;DP_SET_PRE - Digital Potentiometer Set Value
;
;Uses value in W0(7:0) to set Pre-Amp 1 Potentiometer
;Uses value in W1(7:0) to set Pre-Amp 2 Potentiometer
;Uses value in W2(7:0) to set Pre-Amp 3 Potentiometer
;*********************************************************
DP_SET_PRE:
bclr
DP_CPORT,#DP_SCLK_PRE
;Clock Pin Low
nop
;
nop
nop
nop
bclr
DP_CPORT,#DP_CS_PRE
;CS Low
nop
;
nop
nop
nop
;Bit 7 (MSb)
bclr
DP_DPORT,#DP_DIN1_PRE
btsc
W0,#7
bset
DP_DPORT,#DP_DIN1_PRE
nop
bclr
DP_DPORT,#DP_DIN2_PRE
btsc
W1,#7
bset
DP_DPORT,#DP_DIN2_PRE
nop
bclr
DP_DPORT,#DP_DIN3_PRE
btsc
W2,#7
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
194
bset
call
;Bit 6
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 5
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 4
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 3
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 2
bclr
btsc
bset
nop
bclr
btsc
bset
nop
DP_DPORT,#DP_DIN3_PRE
DP_Clock_Pulse_PRE
;Bit Set
;Clock bit through
DP_DPORT,#DP_DIN1_PRE
W0,#6
DP_DPORT,#DP_DIN1_PRE
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
DP_DPORT,#DP_DIN2_PRE
W1,#6
DP_DPORT,#DP_DIN2_PRE
DP_DPORT,#DP_DIN3_PRE
W2,#6
DP_DPORT,#DP_DIN3_PRE
DP_Clock_Pulse_PRE
DP_DPORT,#DP_DIN1_PRE
W0,#5
DP_DPORT,#DP_DIN1_PRE
DP_DPORT,#DP_DIN2_PRE
W1,#5
DP_DPORT,#DP_DIN2_PRE
DP_DPORT,#DP_DIN3_PRE
W2,#5
DP_DPORT,#DP_DIN3_PRE
DP_Clock_Pulse_PRE
DP_DPORT,#DP_DIN1_PRE
W0,#4
DP_DPORT,#DP_DIN1_PRE
DP_DPORT,#DP_DIN2_PRE
W1,#4
DP_DPORT,#DP_DIN2_PRE
DP_DPORT,#DP_DIN3_PRE
W2,#4
DP_DPORT,#DP_DIN3_PRE
DP_Clock_Pulse_PRE
DP_DPORT,#DP_DIN1_PRE
W0,#3
DP_DPORT,#DP_DIN1_PRE
DP_DPORT,#DP_DIN2_PRE
W1,#3
DP_DPORT,#DP_DIN2_PRE
DP_DPORT,#DP_DIN3_PRE
W2,#3
DP_DPORT,#DP_DIN3_PRE
DP_Clock_Pulse_PRE
DP_DPORT,#DP_DIN1_PRE
W0,#2
DP_DPORT,#DP_DIN1_PRE
DP_DPORT,#DP_DIN2_PRE
W1,#2
DP_DPORT,#DP_DIN2_PRE
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
195
bclr
DP_DPORT,#DP_DIN3_PRE
btsc
W2,#2
bset
DP_DPORT,#DP_DIN3_PRE
call
DP_Clock_Pulse_PRE
;Bit 1
bclr
DP_DPORT,#DP_DIN1_PRE
btsc
W0,#1
bset
DP_DPORT,#DP_DIN1_PRE
nop
bclr
DP_DPORT,#DP_DIN2_PRE
btsc
W1,#1
bset
DP_DPORT,#DP_DIN2_PRE
nop
bclr
DP_DPORT,#DP_DIN3_PRE
btsc
W2,#1
bset
DP_DPORT,#DP_DIN3_PRE
call
DP_Clock_Pulse_PRE
;Bit 0 (LSb)
bclr
DP_DPORT,#DP_DIN1_PRE
btsc
W0,#0
bset
DP_DPORT,#DP_DIN1_PRE
nop
bclr
DP_DPORT,#DP_DIN2_PRE
btsc
W1,#0
bset
DP_DPORT,#DP_DIN2_PRE
nop
bclr
DP_DPORT,#DP_DIN3_PRE
btsc
W2,#0
bset
DP_DPORT,#DP_DIN3_PRE
call
DP_Clock_Pulse_PRE
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
nop
;
nop
;
nop
;
nop
;
bset
DP_CPORT,#DP_CS_PRE
;CS High
nop
;
nop
;
nop
;
nop
;
bset
DP_CPORT,#DP_SCLK_PRE
;Clock Pin High
return
;
;*********************************************************
;*********************************************************
;DP_SET_PST - Digital Potentiometer Set Value
;
;Uses value in W0(7:0) to set Post-Amp 1 Potentiometer
;Uses value in W1(7:0) to set Post-Amp 2 Potentiometer
;Uses value in W2(7:0) to set Post-Amp 3 Potentiometer
;*********************************************************
DP_SET_PST:
bclr
DP_CPORT,#DP_SCLK_PST
;Clock Pin Low
nop
;
nop
;
nop
;
nop
;
bclr
DP_CPORT,#DP_CS_PST
;CS Low
nop
;
nop
;
nop
;
nop
;
;Bit 7 (MSb)
196
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 6
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 5
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 4
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
call
;Bit 3
bclr
btsc
bset
nop
bclr
btsc
bset
nop
bclr
btsc
bset
DP_DPORT,#DP_DIN1_PST
W0,#7
DP_DPORT,#DP_DIN1_PST
DP_DPORT,#DP_DIN2_PST
W1,#7
DP_DPORT,#DP_DIN2_PST
DP_DPORT,#DP_DIN3_PST
W2,#7
DP_DPORT,#DP_DIN3_PST
DP_Clock_Pulse_PST
DP_DPORT,#DP_DIN1_PST
W0,#6
DP_DPORT,#DP_DIN1_PST
DP_DPORT,#DP_DIN2_PST
W1,#6
DP_DPORT,#DP_DIN2_PST
DP_DPORT,#DP_DIN3_PST
W2,#6
DP_DPORT,#DP_DIN3_PST
DP_Clock_Pulse_PST
DP_DPORT,#DP_DIN1_PST
W0,#5
DP_DPORT,#DP_DIN1_PST
DP_DPORT,#DP_DIN2_PST
W1,#5
DP_DPORT,#DP_DIN2_PST
DP_DPORT,#DP_DIN3_PST
W2,#5
DP_DPORT,#DP_DIN3_PST
DP_Clock_Pulse_PST
DP_DPORT,#DP_DIN1_PST
W0,#4
DP_DPORT,#DP_DIN1_PST
DP_DPORT,#DP_DIN2_PST
W1,#4
DP_DPORT,#DP_DIN2_PST
DP_DPORT,#DP_DIN3_PST
W2,#4
DP_DPORT,#DP_DIN3_PST
DP_Clock_Pulse_PST
DP_DPORT,#DP_DIN1_PST
W0,#3
DP_DPORT,#DP_DIN1_PST
DP_DPORT,#DP_DIN2_PST
W1,#3
DP_DPORT,#DP_DIN2_PST
DP_DPORT,#DP_DIN3_PST
W2,#3
DP_DPORT,#DP_DIN3_PST
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
197
call
DP_Clock_Pulse_PST
;Bit 2
bclr
DP_DPORT,#DP_DIN1_PST
btsc
W0,#2
bset
DP_DPORT,#DP_DIN1_PST
nop
bclr
DP_DPORT,#DP_DIN2_PST
btsc
W1,#2
bset
DP_DPORT,#DP_DIN2_PST
nop
bclr
DP_DPORT,#DP_DIN3_PST
btsc
W2,#2
bset
DP_DPORT,#DP_DIN3_PST
call
DP_Clock_Pulse_PST
;Bit 1
bclr
DP_DPORT,#DP_DIN1_PST
btsc
W0,#1
bset
DP_DPORT,#DP_DIN1_PST
nop
bclr
DP_DPORT,#DP_DIN2_PST
btsc
W1,#1
bset
DP_DPORT,#DP_DIN2_PST
nop
bclr
DP_DPORT,#DP_DIN3_PST
btsc
W2,#1
bset
DP_DPORT,#DP_DIN3_PST
call
DP_Clock_Pulse_PST
;Bit 0 (LSb)
bclr
DP_DPORT,#DP_DIN1_PST
btsc
W0,#0
bset
DP_DPORT,#DP_DIN1_PST
nop
bclr
DP_DPORT,#DP_DIN2_PST
btsc
W1,#0
bset
DP_DPORT,#DP_DIN2_PST
nop
bclr
DP_DPORT,#DP_DIN3_PST
btsc
W2,#0
bset
DP_DPORT,#DP_DIN3_PST
call
DP_Clock_Pulse_PST
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;
;Assume Bit Clear
;Send out bit
;Bit Set
;Clock bit through
nop
;
nop
;
nop
;
nop
;
bset
DP_CPORT,#DP_CS_PST
;CS High
nop
;
nop
;
nop
;
nop
;
bset
DP_CPORT,#DP_SCLK_PST
;Clock Pin High
return
;
;*********************************************************
;*****DP Clock Pulse PRE**********************************
DP_Clock_Pulse_PRE:
bset
DP_CPORT,#DP_SCLK_PRE
;Clock Pin High
nop
;
nop
;
nop
;
nop
;
nop
;
bclr
DP_CPORT,#DP_SCLK_PRE
;Clock Pin Low
return
;
198
;*********************************************************
;*****DP Clock Pulse POST*********************************
DP_Clock_Pulse_PST:
bset
DP_CPORT,#DP_SCLK_PST
;Clock Pin High
nop
;
nop
;
nop
;
nop
;
nop
;
bclr
DP_CPORT,#DP_SCLK_PST
;Clock Pin Low
return
;
;*********************************************************
;*************************************************************
;********Tone Decoder Routines********************************
;TD_INIT - Tone Decoder Initialization
;*********************************************************
TD_INIT:
bset
TD_TRIS,#TD_OUT1
;Input
nop
bset
TD_TRIS,#TD_OUT2
;Input
nop
bset
TD_TRIS,#TD_OUT3
;Input
return
;
;*********************************************************
;*************************************************************
;********LED Routines*************************************
;LED_INIT - LED Initialization
;*********************************************************
LED_INIT:
bclr
LED_TRIS,#LED1
;Output
bclr
LED_PORT,#LED1
;
;
bclr
LED_TRIS,#LED2
;Output
; bclr
LED_PORT,#LED2
;
bclr
LED_TRIS,#LED3
;Output
bclr
LED_PORT,#LED3
;
return
;
;*********************************************************
;*************************************************************
;********Transducer Driver Routines***************************
;*********************************************************
;TDC_INIT - Transducer Driver Circuit Initialization
;*********************************************************
TDC_INIT:
bclr
TDC_ETRIS,#TDC_MODE
;Output
bset
TDC_EPORT,#TDC_MODE
;
bset
TDC_ETRIS,#TDC_NFLT
;Output
nop
bclr
bset
bclr
bclr
mov
mov
mov
mov
mov
mov
mov
TDC_TRIS,#TDC_PHASE
TDC_PORT,#TDC_PHASE
TDC_TRIS,#TDC_ENABLE
TDC_PORT,#TDC_ENABLE
#145,W0
W0,TDC_DLYVAL
#0x0131,W0
W0,BIGTOH
#0x2D00,W0
W0,BIGTOL
#0x0000,W0
;Output
;
;Output
;
;load counter
;
;Set Big Timeout Default Value
;
;
;
;
199
mov
W0,SMALLTOH
;Set Small Timeout Default Value
mov
#0x4E20,W0
;
mov
W0,SMALLTOL
;
mov
#45,W0
;
mov
W0,TDC_NUMCYC
;
return
;
;*********************************************************
;*********************************************************
;TDC_OUT - Transducer Driver Circuit Output
;*********************************************************
TDC_OUT:
bset
TDC_PORT,#TDC_ENABLE
;Start Output
nop
;
TDC_RPT:
bset
TDC_PORT,#TDC_PHASE
;Change Current Direction
call
TDC_DLY
;delay
nop
nop
;(make up for loop time)
nop
;
bclr
TDC_PORT,#TDC_PHASE
;Change Current Direction
call
TDC_DLY
;
nop
;match time output routine
goto
TDC_RPT
;
bclr
TDC_PORT,#TDC_ENABLE
;Stop Output
return
;
;*********************************************************
;*********************************************************
;TDC_TOUT - Transducer Driver Circuit Timed Output
;Amount of cycles to output passed via TDC_NUMCYC
;*********************************************************
TDC_TOUT:
mov
TDC_NUMCYC,W1
;Set number of cycles
mov
mov
mov
mov
call
bset
nop
TDC_TRPT:
bset
call
nop
nop
nop
bclr
call
dec
bra
BIGTOH,W0
W0,PR5
BIGTOL,W0
W0,PR4
Timer45_clear
TDC_PORT,#TDC_ENABLE
;Set Big Timout value
;
;
;
;Reset Timeout Timer
;Start Output
;
TDC_PORT,#TDC_PHASE
TDC_DLY
TDC_PORT,#TDC_PHASE
TDC_DLY
W1,W1
NZ,TDC_TRPT
;Change Current Direction
;delay
;(make up for loop time)
;
;Change Current Direction
;
;decrement cycle count
;if not yet 0, repeat
bclr
TDC_PORT,#TDC_ENABLE
;Stop Output
return
;
;*********************************************************
;*********************************************************
;TDC_DLY - Transducer Driver Circuit Delay (Sets Freq)
;*********************************************************
TDC_DLY:
mov
TDC_DLYVAL,W0
;load counter
;#145 = 45kHz @ 40 MIPS
TDC_DLY_2:
;
200
dec
W0,W0
;
bra
NZ,TDC_DLY_2
;Delayed Set Time?
return
;yep
;*********************************************************
;*************************************************************
;*************************************************************
;********Timer Routines***************************************
;*********************************************************
;Timer45_init - Timers 4/5 Init (use as a 32-bit timer)
;
;Setup Timer 4/5 to operated as a single 32-bit timer
;*********************************************************
Timer45_init:
bclr
PMD1,#T4MD
;Make sure timers are enabled
nop
;
bclr
PMD1,#T5MD
;
;mov
#0x0038,W0
;Setup 32-bit timer, 1:256 prescaler
mov
#0x0008,W0
;Setup 32-bit
timer, 1:1 prescaler
mov
W0,T4CON
;(Timer 4/5)
;Not setting up any interrupts
bclr
T4CON,#15
;Ensure timer is stopped
return
;
;*********************************************************
;*********************************************************
;Timer45_clear - Timers 4/5 Clear
;
;Clear 32-bit timer (Start at 0x00000000)
;*********************************************************
Timer45_clear:
bclr
T4CON,#15
;stop timer
mov
#0x0000,W0
;Write 0x0000 to MSW
mov
W0,TMR5HLD
;(Timer 4/5)
mov
W0,TMR4
;(Timer 4/5)
bclr
IFS1,#T5IF
;Clear interrupt flag
bset
T4CON,#15
;start timer
return
;
;*********************************************************
;*********************************************************
;Timer45_read - Timers 4/5 Read
;
;Read the 32-bit timer
;*********************************************************
Timer45_read:
mov
TMR4,W0
;Transfer the LSW into W1
mov
TMR5HLD, W1
;Transfer the MSW from the
;holding register to W0
return
;
;*********************************************************
;*********************************************************
;IC_INIT - Setup input capture
;
;Will setup the input capture feature to record the
;arrival of the three tone decoder inputs
;*********************************************************
IC_INIT:
mov
#0x0080,W0
;Ensure IC is disabled
mov
W0,IC1CON
;
mov
W0,IC2CON
;
mov
W0,IC3CON
;
bclr
PMD2,#IC1MD
;Make sure input capture modules
201
nop
bclr
PMD2,#IC2MD
;are not disabled
nop
bclr
PMD2,#IC3MD
;
bclr
PMD1,#T2MD
;Make sure timer2 module is enabled
mov
#0x8000,W0
;Setup Timer2 as 16-bit timer
mov
W0,T2CON
;
return
;
;*********************************************************
;*********************************************************
;IC_START - Start Input Capture Routine
;
;Will begin checking for incoming signals from the tone
;decoders. If no signals are detected within 500ms, it
;will timeout. If a signal is detected, it will wait up
;to 500us for the other signals to be detected as well.
;If these are not detected, a timeout will occur. If all
;signals are detected, the value of the 16-bit timer will
;be returned in the TRANSTIME variables. The 32-bit range
;time will be returned in RANGETIME variables.
;*********************************************************
;MUST SET PR REGISTERS FOR TIMEOUT BEFORE STARTING TIMER!!!!!
IC_START:
mov
#0x0082,W0
;Setup IC registers, falling edge detect
mov
W0,IC1CON
;
mov
W0,IC2CON
;
mov
W0,IC3CON
;
clr
TRANSORDER
;Clear transducer order register
;Detection Enabled, big Timeout Should've been Started
IC_WAIT:
btsc
IC1CON,#3
;Check if IC1 event occurred
goto
ICEO1
;IC1 Event Occurred
btsc
IC2CON,#3
;Check if IC2 event occurred
goto
ICEO2
;IC2 Event Occurred
btsc
IC3CON,#3
;Check if IC3 event occurred
goto
ICEO3
;IC3 Event Occurred
btsc
IFS1,#T5IF
;Check for big timeout
goto
IC_NORETURN
;no return signal received
goto
IC_WAIT
;
;Transducer 1 received signal first, start small Timeout
;wait for next 2 signals
ICEO1:
call
Timer45_read
;store ranging time
mov
W0,RANGETIMEL
;
mov
W1,RANGETIMEH
;
mov
IC1BUF,W0
;Retrieve event time
mov
W0,TRANSTIME1
;
mov
mov
mov
mov
call
ICEO1_wait:
btsc
goto
btsc
goto
btsc
SMALLTOH,W0
W0,PR5
SMALLTOL,W0
W0,PR4
Timer45_clear
;Set Small Timeout value
;
;
;
;Reset Timeout Timer
IC2CON,#3
ICEO12
IC3CON,#3
ICEO13
IFS1,#T5IF
;Check if IC2 event occurred
;IC2 Event Occurred 2nd
;Check if IC3 event occurred
;IC3 Event Occurred 2nd
;Check for small timeout
202
goto
IC_NOTALLRETURN
goto
ICEO1_wait
;1,2
ICEO12:
mov
IC2BUF,W0
mov
W0,TRANSTIME2
ICEO12_wait:
btsc
IC3CON,#3
goto
ICEO123
btsc
IFS1,#T5IF
goto
IC_NOTALLRETURN
goto
ICEO12_wait
;1,3
ICEO13:
mov
IC3BUF,W0
mov
W0,TRANSTIME3
ICEO13_wait:
btsc
IC2CON,#3
goto
ICEO132
btsc
IFS1,#T5IF
goto
IC_NOTALLRETURN
goto
ICEO13_wait
;1,2,3
ICEO123:
mov
#0x01,W0
mov
W0,TRANSORDER
mov
IC3BUF,W0
mov
W0,TRANSTIME3
return
;1,3,2
ICEO132:
mov
#0x02,W0
mov
W0,TRANSORDER
mov
IC2BUF,W0
mov
W0,TRANSTIME2
return
;not all transducers received signal
;
;Retrieve event time
;
;Check if IC3 event occurred
;IC3 Event Occurred last
;Check for small timeout
;not all transducers received signal
;
;Retrieve event time
;
;Check if IC2 event occurred
;IC2 Event Occurred last
;Check for small timeout
;not all transducers received signal
;
;Set Transducer Order
;
;Retrieve event time
;
;All 3 transducers responded.. return
;Set Transducer Order
;
;Retrieve event time
;
;All 3 transducers responded.. return
;Transducer 2 received signal first, start small Timeout
;wait for next 2 signals
ICEO2:
call
Timer45_read
;store ranging time
mov
W0,RANGETIMEL
;
mov
W1,RANGETIMEH
;
mov
IC2BUF,W0
;Retrieve event time
mov
W0,TRANSTIME2
;
mov
mov
mov
mov
call
ICEO2_wait:
btsc
goto
btsc
goto
btsc
goto
goto
;2,1
ICEO21:
mov
mov
SMALLTOH,W0
W0,PR5
SMALLTOL,W0
W0,PR4
Timer45_clear
;Set Small Timeout value
;
;
;
;Reset Timeout Timer
IC1CON,#3
ICEO21
IC3CON,#3
ICEO23
IFS1,#T5IF
IC_NOTALLRETURN
ICEO2_wait
;Check if IC1 event occurred
;IC1 Event Occurred 2nd
;Check if IC3 event occurred
;IC3 Event Occurred 2nd
;Check for small timeout
;not all transducers received signal
;
IC1BUF,W0
W0,TRANSTIME1
;Retrieve event time
;
203
ICEO21_wait:
btsc
IC3CON,#3
goto
ICEO213
btsc
IFS1,#T5IF
goto
IC_NOTALLRETURN
goto
ICEO21_wait
;2,3
ICEO23:
mov
IC3BUF,W0
mov
W0,TRANSTIME3
ICEO23_wait:
btsc
IC1CON,#3
goto
ICEO231
btsc
IFS1,#T5IF
goto
IC_NOTALLRETURN
goto
ICEO23_wait
;2,1,3
ICEO213:
mov
#0x03,W0
mov
W0,TRANSORDER
mov
IC3BUF,W0
mov
W0,TRANSTIME3
return
;2,3,1
ICEO231:
mov
#0x04,W0
mov
W0,TRANSORDER
mov
IC1BUF,W0
mov
W0,TRANSTIME1
return
;Check if IC3 event occurred
;IC3 Event Occurred last
;Check for small timeout
;not all transducers received signal
;
;Retrieve event time
;
;Check if IC1 event occurred
;IC1 Event Occurred last
;Check for small timeout
;not all transducers received signal
;
;Set Transducer Order
;
;Retrieve event time
;
;All 3 transducers responded.. return
;Set Transducer Order
;
;Retrieve event time
;
;All 3 transducers responded.. return
;Transducer 3 received signal first, start small Timeout
;wait for next 2 signals
ICEO3:
call
Timer45_read
;store ranging time
mov
W0,RANGETIMEL
;
mov
W1,RANGETIMEH
;
mov
IC3BUF,W0
;Retrieve event time
mov
W0,TRANSTIME3
;
mov
SMALLTOH,W0
mov
W0,PR5
mov
SMALLTOL,W0
mov
W0,PR4
call
Timer45_clear
ICEO3_wait:
btsc
IC1CON,#3
goto
ICEO31
btsc
IC2CON,#3
goto
ICEO32
btsc
IFS1,#T5IF
goto
IC_NOTALLRETURN
goto
ICEO3_wait
;3,1
ICEO31:
mov
IC1BUF,W0
mov
W0,TRANSTIME1
ICEO31_wait:
btsc
IC2CON,#3
goto
ICEO312
btsc
IFS1,#T5IF
goto
IC_NOTALLRETURN
goto
ICEO31_wait
;Set Small Timeout value
;
;
;
;Reset Timeout Timer
;Check if IC1 event occurred
;IC1 Event Occurred 2nd
;Check if IC2 event occurred
;IC2 Event Occurred 2nd
;Check for small timeout
;not all transducers received signal
;
;Retrieve event time
;
;Check if IC2 event occurred
;IC2 Event Occurred last
;Check for small timeout
;not all transducers received signal
;
204
;3,2
ICEO32:
mov
IC2BUF,W0
mov
W0,TRANSTIME2
ICEO32_wait:
btsc
IC1CON,#3
goto
ICEO321
btsc
IFS1,#T5IF
goto
IC_NOTALLRETURN
goto
ICEO32_wait
;3,1,2
ICEO312:
mov
#0x05,W0
mov
W0,TRANSORDER
mov
IC2BUF,W0
mov
W0,TRANSTIME2
return
;3,2,1
ICEO321:
mov
#0x06,W0
mov
W0,TRANSORDER
mov
IC1BUF,W0
mov
W0,TRANSTIME1
return
;Time out routines
IC_NORETURN:
mov
#0x00,W0
mov
W0,TRANSORDER
return
;Retrieve event time
;
;Check if IC1 event occurred
;IC1 Event Occurred last
;Check for small timeout
;not all transducers received signal
;
;Set Transducer Order
;
;Retrieve event time
;
;All 3 transducers responded.. return
;Set Transducer Order
;
;Retrieve event time
;
;All 3 transducers responded.. return
;Set Transducer Order to timeout
;
;
IC_NOTALLRETURN:
mov
#0x07,W0
;Set Transducer Order to timeout
mov
W0,TRANSORDER
;
return
;
;*********************************************************
;********DELAY ROUTINES***************************************
;*********************************************************
;delay100ms ;
;Delays 100ms
;*********************************************************
delay100ms:
mov
#20,W4
;delay ~100ms
delayloop100ms:
call
delay5ms
;
dec
W4,W4
;
bra
NZ,delayloop100ms
;
return
;
delay5ms:
mov
#40,W2
;load counter
delayloop:
call
delay125us
;delay 125us
dec
W2,W2
;Delayed 5ms?
bra
NZ,delayloop
;
return
;yep
;*********************************************************
;*********************************************************
;delay125us ;
205
;Delays 125us
;*********************************************************
delay125us:
mov
#1664,W3
;load counter
delayloop2:
;
dec
W3,W3
;
bra
NZ,delayloop2
;Delayed 125us?
nop
nop
return
;yep
;*********************************************************
;*************************************************************
.end
206
;**********************************************************************************
;************************ TRANSPONDER MICROCONTROLLER CODE ************************
;**********************************************************************************
.equ __33FJ12GP202, 1
.include "p33FJ12GP202.inc"
;..............................................................................
;Configuration bits:
;..............................................................................
config __FOSC, FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_EC
;Turn off clock switching and
;fail-safe clock monitoring and
;use the External Clock as the
;system clock
config __FWDT, FWDTEN_OFF & WINDIS_OFF;Turn off Watchdog Timer
config __FPOR, FPWRT_PWR128
;Set Power on Timer 128 mSec
config __FOSCSEL, FNOSC_PRIPLL & IESO_OFF ;Setup Oscillator (w/PLL)
config __FGS, GSS_OFF & GCP_OFF & GWRP_OFF ;Disable Code protect
config __FBS, BSS_NO_FLASH & BWRP_WRPROTECT_OFF ;
;..............................................................................
;Program Specific Constants (literals used in code)
;..............................................................................
;----DIGITAL POTENTIOMETER EQUATES-------------.equ
DP_PORT,PORTA
;
.equ
DP_TRIS,TRISA
;
.equ
DP_CS,0
;Chip Select
.equ
DP_SCLK,1
;Clock
.equ
DP_DIN_PRE,4
;Pre-Amp Digital Pot Line
.equ
DP_DIN_PST,3
;Post-Amp Digital Pot Line
;----TRANSDUCER
.equ
.equ
.equ
.equ
.equ
.equ
DRIVER EQUATES-----------------TDC_PORT,PORTB
;
TDC_TRIS,TRISB
;
TDC_MODE,8
;
TDC_PHASE,7
;
TDC_ENABLE,6
;
TDC_NFLT,0
;
;----TONE DECODER EQUATES----------------------.equ
TD_PORT,PORTB
;
.equ
TD_TRIS,TRISB
;
.equ
TD_OUT,11
;
;----ANALOG INPUT EQUATES----------------------.equ
AI_PORT,PORTB
;
.equ
AI_TRIS,TRISB
;
.equ
AI_PRE,13
;
.equ
AI_POST,12
;
;..............................................................................
;Global Declarations:
;..............................................................................
.global __reset
;The label for the first line of code.
207
;..............................................................................
;Constants stored in Program space
;..............................................................................
;
.section .myconstbuffer, code
;
.palign 2
;Align next word stored in Program space to an
;
;address that is a multiple of 2
;ps_coeff:
;
.hword
0x0002, 0x0003, 0x0005, 0x000A
;..............................................................................
;Uninitialized variables in X-space in data memory
;..............................................................................
.section .xbss, bss, xmemory
TEMP:
TDC_DLYVAL:
TDC_NUMCYC:
.space
.space
.space
2
2
2
;..............................................................................
;Uninitialized variables in Y-space in data memory
;..............................................................................
;
;y_input:
.section .ybss, bss, ymemory
.space 2*SAMPLES
;..............................................................................
;Initialized variables in data memory
;..............................................................................
;..............................................................................
;Uninitialized variables in Near data memory (Lower 8Kb of RAM)
;..............................................................................
;
.section .nbss, bss, near
.section vars,bss,address(0x900)
;..............................................................................
;Code Section in Program Memory
;..............................................................................
.text
;Start of Code section
__reset:
MOV #__SP_init, W15
;Initalize the Stack Pointer
MOV #__SPLIM_init, W0
;Initialize the Stack Pointer Limit Register
MOV W0, SPLIM
NOP
;Add NOP to follow SPLIM initialization
main:
;Initialize PLL to proper frequency
;PLL will work on startup if 4mHz<Fin<8mHz
;(it was checked that PLL settings will within
;limits during this PLL update process)
mov
#0x00C0,W0
;PLLPRE=2,PLLPOST=8 (FOR IC=8mhz)
mov
W0,CLKDIV
;
mov
#0x003E,W0
;Set PLL Multiplier=64 (For IC = 8mhz)
mov
W0,PLLFBD
;
208
;Disable all modules
mov
#0xFFFF,W0
mov
W0,PMD1
mov
W0,PMD2
;
;
;
;Disable all open-drains
mov
#0x0000,W0
mov
W0,ODCA
mov
W0,ODCB
;
;Port A
;Port B
;Disable Analog Function of I/O Pins
mov
#0xFFFF,W0
;
mov
W0,AD1PCFGL
;
;Initialize
call
call
call
Everything
DP_INIT
TD_INIT
TDC_INIT
;Initialize Digital Potentiometers
;Initialize Tone Decoder
;Initialize Transducer Driver Circuit
mov
#35,W0
;load counter (#35 = ~35khz, #170 =
audible tone)
mov
W0,TDC_DLYVAL
;delay value (sets
transmit frequency)
mov
#7000,W0
;Load number of
transmit cycles
mov
W0,TDC_NUMCYC
;sets pulse length (70
= 2ms)
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
call
delay100ms
;
mov
#90,W0
;Set front end gain ~100
mov
#127,W1
;Set back end gain min
call
DP_SET
;Set Potentiometer Values
mainloop:
call
TDC_TOUT
;Main Loop Programmed to output 1ms pulse
call
delay100ms
;approximately 3 times per second
call
delay100ms
;
call
delay100ms
;In actual practice, this loop should wait for
goto
mainloop
;an interrogation pulse, then respond.
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;..............................................................................
;Timer 1 Interrupt Service Routine
;Example context save/restore in the ISR performed using PUSH.D/POP.D
;instruction. The instruction pushes two words W4 and W5 on to the stack on
;entry into ISR and pops the two words back into W4 and W5 on exit from the ISR
;..............................................................................
;__T1Interrupt:
;
PUSH.D W4
;Save context using double-word PUSH
;<<insert more user code here>>
;
BCLR IFS0, #T1IF
;
;
POP.D W4
RETFIE
;Clear the Timer1 Interrupt flag Status
;bit.
;Retrieve context POP-ping from Stack
;Return from Interrupt Service routine
;--------End of All Code Sections ---------------------------------------------
209
;********Digital Potentiometer Routines***********************
;*********************************************************
;DP_INIT - Digital Potentiometer Initialization
;*********************************************************
DP_INIT:
bclr
DP_TRIS,#DP_CS
;CS Output
bset
DP_PORT,#DP_CS
;
bclr
DP_TRIS,#DP_SCLK
;SCLK Output
bset
DP_PORT,#DP_SCLK
;
bclr
DP_TRIS,#DP_DIN_PRE
;DIN Output
bclr
DP_PORT,#DP_DIN_PRE
;
bclr
DP_TRIS,#DP_DIN_PST
;DIN Output
bclr
DP_PORT,#DP_DIN_PST
;
return
;
;*********************************************************
;*********************************************************
;DP_SET - Digital Potentiometer Set Value
;
;Uses value in W0(7:0) to set Pre-Amp Potentiometer
;Uses value in W1(7:0) to set Post-Amp Potentiometer
;*********************************************************
DP_SET:
bclr
DP_PORT,#DP_SCLK
;Clock Pin Low
nop
;
bclr
DP_PORT,#DP_CS
;CS Low
nop
;
bclr
btsc
bset
nop
bclr
btsc
bset
call
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
W0,#7
;Send out MSB (#7)
DP_PORT,#DP_DIN_PRE ;Bit Set
;
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
W1,#7
;Send out MSB (#7)
DP_PORT,#DP_DIN_PST ;Bit Set
DP_Clock_Pulse
;Clock bit through
bclr
btsc
bset
nop
bclr
btsc
bset
call
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
W0,#6
;Send out bit (#6)
DP_PORT,#DP_DIN_PRE ;Bit Set
;
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
W1,#6
;Send out bit (#6)
DP_PORT,#DP_DIN_PST ;Bit Set
DP_Clock_Pulse
;Clock bit through
bclr
btsc
bset
nop
bclr
btsc
bset
call
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
W0,#5
;Send out bit (#5)
DP_PORT,#DP_DIN_PRE ;Bit Set
;
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
W1,#5
;Send out bit (#5)
DP_PORT,#DP_DIN_PST ;Bit Set
DP_Clock_Pulse
;Clock bit through
bclr
btsc
bset
nop
bclr
btsc
bset
call
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
W0,#4
;Send out bit (#4)
DP_PORT,#DP_DIN_PRE ;Bit Set
;
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
W1,#4
;Send out bit (#4)
DP_PORT,#DP_DIN_PST ;Bit Set
DP_Clock_Pulse
;Clock bit through
210
bclr
btsc
bset
nop
bclr
btsc
bset
call
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
W0,#3
;Send out bit (#3)
DP_PORT,#DP_DIN_PRE ;Bit Set
;
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
W1,#3
;Send out bit (#3)
DP_PORT,#DP_DIN_PST ;Bit Set
DP_Clock_Pulse
;Clock bit through
bclr
btsc
bset
nop
bclr
btsc
bset
call
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
W0,#2
;Send out bit (#2)
DP_PORT,#DP_DIN_PRE ;Bit Set
;
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
W1,#2
;Send out bit (#2)
DP_PORT,#DP_DIN_PST ;Bit Set
DP_Clock_Pulse
;Clock bit through
bclr
btsc
bset
nop
bclr
btsc
bset
call
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
W0,#1
;Send out bit (#1)
DP_PORT,#DP_DIN_PRE ;Bit Set
;
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
W1,#1
;Send out bit (#1)
DP_PORT,#DP_DIN_PST ;Bit Set
DP_Clock_Pulse
;Clock bit through
bclr
DP_PORT,#DP_DIN_PRE ;Assume Bit Clear
btsc
W0,#0
;Send out bit (#0)
bset
DP_PORT,#DP_DIN_PRE ;Bit Set
nop
;
bclr
DP_PORT,#DP_DIN_PST ;Assume Bit Clear
btsc
W1,#0
;Send out bit (#0)
bset
DP_PORT,#DP_DIN_PST ;Bit Set
call
DP_Clock_Pulse
;Clock bit through
nop
;
nop
;
bset
DP_PORT,#DP_CS
;CS High
nop
;
bset
DP_PORT,#DP_SCLK
;Clock Pin High
return
;
;*********************************************************
;*****DP Clock Pulse**************************************
DP_Clock_Pulse:
bset
DP_PORT,#DP_SCLK
;Clock Pin High
nop
;
;
nop
;
bclr
DP_PORT,#DP_SCLK
;Clock Pin Low
return
;
;*********************************************************
;*************************************************************
;********Tone Decoder Routines********************************
;TD_INIT - Tone Decoder Initialization
;*********************************************************
TD_INIT:
bset
TD_TRIS,#TD_OUT
;Input
return
;
;*********************************************************
;*************************************************************
;********Transducer Driver Routines***************************
211
;*********************************************************
;TDC_INIT - Transducer Driver Circuit Initialization
;*********************************************************
TDC_INIT:
bclr
TDC_TRIS,#TDC_MODE
;Output
bset
TDC_PORT,#TDC_MODE
;
bclr
TDC_TRIS,#TDC_PHASE
;Output
bset
TDC_PORT,#TDC_PHASE
;
bclr
TDC_TRIS,#TDC_ENABLE
;Output
bclr
TDC_PORT,#TDC_ENABLE
;
bset
TDC_TRIS,#TDC_NFLT
;Output
mov
mov
#293,W0
W0,TDC_DLYVAL
;
;load counter
mov
mov
#45,W0
W0,TDC_NUMCYC
;
;
return
;
;*********************************************************
;*********************************************************
;TDC_OUT - Transducer Driver Circuit Output
;*********************************************************
TDC_OUT:
bset
TDC_PORT,#TDC_ENABLE
;Start Output
nop
;
TDC_RPT:
bset
TDC_PORT,#TDC_PHASE
;Change Current Direction
call
TDC_DLY
;delay
nop
;(make up for loop time)
nop
;
bclr
TDC_PORT,#TDC_PHASE
;Change Current Direction
call
TDC_DLY
;
goto
TDC_RPT
;
bclr
TDC_PORT,#TDC_ENABLE
;Stop Output
return
;
;*********************************************************
;*********************************************************
;TDC_TOUT - Transducer Driver Circuit Timed Output
;Amount of cycles to output passed via TDC_NUMCYC
;*********************************************************
TDC_TOUT:
mov
TDC_NUMCYC,W1
;Set number of cycles
bset
TDC_PORT,#TDC_ENABLE
;Start Output
nop
TDC_TRPT:
bset
call
nop
nop
nop
bclr
call
dec
bra
TDC_PORT,#TDC_PHASE
TDC_DLY
TDC_PORT,#TDC_PHASE
TDC_DLY
W1,W1
NZ,TDC_TRPT
;Change Current Direction
;delay
;(make up for loop time)
;
;Change Current Direction
;
;decrement cycle count
;if not yet 0, repeat
bclr
TDC_PORT,#TDC_ENABLE
;Stop Output
return
;
;*********************************************************
212
;*********************************************************
;TDC_DLY - Transducer Driver Circuit Delay (Sets Freq)
;*********************************************************
TDC_DLY:
mov
TDC_DLYVAL,W0
;load counter (35 = ~35kHz)
;#170 = Audible Tone
TDC_DLY_2:
;
dec
W0,W0
;
bra
NZ,TDC_DLY_2
;Delayed Set Time?
return
;yep
;*********************************************************
;*************************************************************
;*************************************************************
;;********Timer Routines***************************************
;;*********************************************************
;;Timer23_init - Timers 2/3 Init (use as a 32-bit timer)
;;
;;Setup Timer 2/3 to operated as a single 32-bit timer
;;*********************************************************
;Timer23_init:
;
mov
#0x0038,W0
;Setup 32-bit timer
;
mov
W0,T2CON
;(Timer 2/3)
;
;Not setting up any interrupts
;
bset
T2CON,#15
;start timer
;
return
;
;;*********************************************************
;;*********************************************************
;;Timer23_clear - Timers 2/3 Clear
;;
;;Clear 32-bit timer (Start at 0x00000000)
;;*********************************************************
;Timer23_clear:
;
mov
#0x0000,W0
;Write 0x0000 to MSW
;
mov
W0,TMR3HLD
;(Timer 2/3)
;
mov
W0,TMR2
;(Timer 2/3)
;
return
;
;;*********************************************************
;;*********************************************************
;;Timer23_read - Timers 2/3 Read
;;
;;Read the 32-bit timer
;;*********************************************************
;Timer23_read:
;
mov
TMR2,W0
;Transfer the LSW into W1
;
mov
TMR3HLD, W1
;Transfer the MSW from the
;
;holding register to W0
;
return
;
;;*********************************************************
;;*********************************************************
;;OnePPS_init - 1PPS Init (INT4)
;;
;;Setup 1PPS pin as input and interrupt used to clear timer
;;*********************************************************
;OnePPS_init:
;
bset
INT_TRIS,#GPS_INT
;Set 1PPS pin as an input
;;Setup INT4 interrupt
;
bclr
INTCON2,#INT4EP
;Interrupt on positive edge
;
bset
IPC13,#9
;Set interrupt priority
;
;to level 6 (default level 4)
;
bclr
INTCON1,#NSTDIS
;Enable nested interrupts
;
bclr
IFS3,#INT4IF
;Clear interrupt flag
213
;
bset
IEC3,#INT4IE
;Enable INT4 interrupt
;
return
;
;;*********************************************************
;;*********************************************************
;;__INT4Interrupt - INT4 Interrupt Routine (1PPS)
;;
;;Clears Timer2/3 when 1PPS interrupt is received
;;*********************************************************
;__INT4Interrupt:
;
;Save context
;
push
W0
;Save W0
;
;Clear Timer 2/3 value
;
mov
#0x0000,W0
;Write 0x0000 to MSW
;
mov
W0,TMR3HLD
;(Timer 2/3)
;
mov
W0,TMR2
;(Timer 2/3)
;
;Restore context
;
pop
W0
;Restore W0
;
bclr
IFS3,#INT4IF
;Clear interrupt flag
;
retfie
;return
;;*********************************************************
;;*************************************************************
;
;
;
;;********Conversion Routines**********************************
;;*********************************************************
;;SNUM2ASCII - Signed Number to ASCII
;;Converts Signed 16-bit value in W0 to 5 ASCII characters plus
;;a sign character.
;;The ASCII values are stored in
;;W5 - Sign (' ' or '-')
;;W4 - ten thousands
;;W3 - thousands
;;W2 - hundreds
;;W1 - tens
;;W0 - ones
;;*********************************************************
;snum2ascii:
;
btss
W0,#15
;Check the sign bit
;
goto
snum2asciipos
;Positive Number
;;negative number, must reverse the
;;2's complement procedure before calling num2bcd
;
mov
#0xFFFF,W5
;Invert all the bits
;
xor
W0,W5,W0
;
;
inc
W0,W0
;add 1
;
call
num2bcd
;
;
mov
#0x002D,W5
;Set Sign character
;
add
#0x30,W0
;Convert BCD to ASCII
;
add
#0x30,W1
;
;
add
#0x30,W2
;
;
add
#0x30,W3
;
;
add
#0x30,W4
;
;
return
;
;snum2asciipos:
;
mov
#0x0020,W5
;Set Sign character
;
call
num2bcd
;Convert digits
;
add
#0x30,W0
;Convert BCD to ASCII
;
add
#0x30,W1
;
;
add
#0x30,W2
;
;
add
#0x30,W3
;
;
add
#0x30,W4
;
;
return
;
;;***********************************************
214
;
;;*********************************************************
;;SNUM2BCD - Signed Number to BCD
;;Converts Signed 16-bit value in W0 to 5 BCD digits plus sign bit
;;The BCD values are stored in
;;W5 - Bit 0 indicates sign... 1 if negative, 0 if positive
;;W4 - ten thousands
;;W3 - thousands
;;W2 - hundreds
;;W1 - tens
;;W0 - ones
;;*********************************************************
;snum2bcd:
;
btss
W0,#15
;Check the sign bit
;
goto
num2bcd
;positive number, will be returned by num2bcd
;
;negative number, must reverse the
;
;2's complement procedure before calling num2bcd
;
mov
#0xFFFF,W5
;Invert all the bits
;
xor
W0,W5,W0
;
;
inc
W0,W0
;add 1
;
call
num2bcd
;
;
mov
#0x0001,W5
;Set sign bit, show negative number
;
return
;
;;***********************************************
;
;;*********************************************************
;;NUM2BCD - Number to BCD
;;Converts 16-bit value in W0 to 5 BCD digits
;;The BCD values are stored in
;;W5 - Temporary Register,
;;W4 - ten thousands
;;W3 - thousands
;;W2 - hundreds
;;W1 - tens
;;W0 - ones
;;*********************************************************
;num2bcd:
;
clr
W4
;Clear the variables to be stored
;
clr
W3
;
;
clr
W2
;
;
clr
W1
;
;
;tenthoutest:
;
mov
#0x2710,W5
;(10,000 in hex)
;
cp
W0,W5
;
;
bra
ltu,thoutest
;Check if W0 >= 10,000
;
;it is
;
sub
W0,W5,W0
;Subtract 10,000 from Incoming number
;
inc.b
W4,W4
;Increment BCD digit
;
bra
tenthoutest
;repeat
;
;thoutest:
;
mov
#0x03E8,W5
;(1,000 in hex)
;
cp
W0,W5
;
;
bra
ltu,hundtest
;Check if W0 >= 1,000
;
;it is
;
sub
W0,W5,W0
;Subtract 1,000 from Incoming number
;
inc.b
W3,W3
;Increment BCD digit
;
bra
thoutest
;repeat
;
;hundtest:
;
mov
#0x0064,W5
;(100 in hex)
;
cp
W0,W5
;
215
;
bra
ltu,tentest
;Check if W0 >= 100
;
;it is
;
sub
W0,W5,W0
;Subtract 100 from Incoming number
;
inc.b
W2,W2
;Increment BCD digit
;
bra
hundtest
;repeat
;
;tentest:
;
mov
#0x000A,W5
;(10 in hex)
;
cp
W0,W5
;
;
bra
ltu,onetest
;Check if W0 >= 10
;
;it is
;
sub
W0,W5,W0
;Subtract 10 from Incoming number
;
inc.b
W1,W1
;Increment BCD digit
;
bra
tentest
;repeat
;
;onetest:
;
;Rest are ones and already stored in W0
;
clr
W5
;Clear to indicate positive sign for snum2bcd
;
return
;done
;;***********************************************
;;*************************************************************
;
;
;
;********DELAY ROUTINES***************************************
;*********************************************************
;delay100ms ;
;Delays 100ms
;*********************************************************
delay100ms:
mov
#20,W4
;delay ~100ms
delayloop100ms:
call
delay5ms
;
dec
W4,W4
;
bra
NZ,delayloop100ms
;
return
;
delay5ms:
mov
#40,W2
;load counter
delayloop:
call
delay125us
;delay 125us
dec
W2,W2
;Delayed 5ms?
bra
NZ,delayloop
;
return
;yep
;*********************************************************
;*********************************************************
;delay125us ;
;Delays 125us
;*********************************************************
delay125us:
mov
#0x014B,W3
;load counter (0x014B for Fcyl=8MHz)
delayloop2:
;
dec
W3,W3
;
bra
NZ,delayloop2
;Delayed 125us?
nop
nop
return
;yep
;*********************************************************
;*********************************************************
;delay71us -
216
;
;Delays 71us
;*********************************************************
delay71us:
mov
#0x00BB,W3
;load counter (0x014B for Fcyl=8MHz)
delayloop271:
;
dec
W3,W3
;
bra
NZ,delayloop271 ;Delayed 71us?
nop
nop
return
;yep
;*********************************************************
;*************************************************************
.end
217
Appendix D: MATLAB Code
218
%GPS Accuracy Computer
%Authored By Doug Bowlus on Dec 28, 2007
close all
clear all
clc
%Known Coordinate
%KC_Lat = DMS_2_DD(34,22,30.97170); %RINCON, PID: EW7931
%KC_Long = DMS_2_DD(119,28,36.69745);
KC_Lat = DMS_2_DD(34,15,13.54656); %Fugro Point 6, In back of office
KC_Long = DMS_2_DD(119,13,34.15617);
[KC_X,KC_Y,KC_Z] = WGS84_2_Cart(KC_Lat,KC_Long,0);
%Load Observed Data
filename = 'LOG4a.txt';
[AP_Hdr,X_Mag,Y_Mag,Z_Mag,X_Tilt,Y_Tilt,RangeTime,TransOrder,Tran1Time,Tran2Time,Tr
an3Time,AP_STime,AP_ETime,Tilt_Time,Mag_Time,GPS_Hdr,UTC_Time,Latitude,N_S,Longitud
e,E_W,Fix_Type,Satellites,HDOP,MSL_Alt,MSL_Units,Geoid_Sep,Geoid_Units,Age_of_Corr,
Checksum] = importuwgps(filename);
[OC_X,OC_Y,OC_Z] = WGS84_2_Cart(Latitude,Longitude,0);
%Compute
Diff_X =
Diff_Y =
Diff_Z =
the difference between observed and known positions
OC_X - KC_X;
OC_Y - KC_Y;
OC_Z - KC_Z;
%Plot the differences
plot3(Diff_X,Diff_Y,Diff_Z,'o')
hold on
%Plot Last Posistion
plot3(Diff_X(end),Diff_Y(end),Diff_Z(end),'go')
%Find Average Position
[AOC_X,AOC_Y,AOC_Z] = WGS84_2_Cart(mean(Latitude),mean(Longitude),0);
%Plot Average Position Difference
AEX = AOC_X - KC_X;
AEY = AOC_Y - KC_Y;
AEZ = AOC_Z - KC_Z;
plot3(AEX,AEY,AEZ,'ro');
hold off
grid on
%Display computed overall Error
E2DRMS = sqrt(Diff_X.^2+Diff_Y.^2+Diff_Z.^2);
SD2DRMS = std(E2DRMS)
Mean_2DRMS = mean(E2DRMS)
Max_2DRMS = max(E2DRMS)
Min_2DRMS = min(E2DRMS)
Fix = mean(Fix_Type)
DurationMIN = length(Fix_Type)./60
219
function
[AP_Hdr,X_Mag,Y_Mag,Z_Mag,X_Tilt,Y_Tilt,RangeTime,TransOrder,Tran1Time,Tran2Time,Tr
an3Time,AP_STime,AP_ETime,Tilt_Time,Mag_Time,GPS_Hdr,UTC_Time,Latitude,N_S,Longitud
e,E_W,Fix_Type,Satellites,HDOP,MSL_Alt,MSL_Units,Geoid_Sep,Geoid_Units,Age_of_Corr,
Checksum] = importuwgps(filename)
%
%importuwgps
%
%Authored by Doug Bowlus on 12/27/2007
%
%[AP_Hdr,X_Mag,Y_Mag,Z_Mag,X_Tilt,Y_Tilt,RangeTime,TransOrder,Tran1Time,Tran2Time,T
ran3Time,AP_STime,AP_ETime,Tilt_Time,Mag_Time,GPS_Hdr,UTC_Time,Latitude,N_S,Longitu
de,E_W,Fix_Type,Satellites,HDOP,MSL_Alt,MSL_Units,Geoid_Sep,Geoid_Units,Age_of_Corr
,Checksum] = importuwgps(filename)
%
%Given the filename for UWGPS log data, this script imports all of it into
%appropriate variable names
%
fid = fopen(filename);
data =
textscan(fid,'%s%f%f%f%f%f%f%f%f%f%f%f%f%f%f%s%f%f%s%f%s%f%f%f%f%s%f%s%f%s',1,'delimiter',',');
AP_Hdr = cellstr(data{1});
X_Mag = double(data{2});
Y_Mag = double(data{3});
Z_Mag = double(data{4});
X_Tilt = double(data{5})./10;
Y_Tilt = double(data{6})./10;
RangeTime = double(data{7}).*125e-9;
TransOrder = double(data{8});
Tran1Time = double(data{9}).*125e-9;
Tran2Time = double(data{10}).*125e-9;
Tran3Time = double(data{11}).*125e-9;
AP_STime = double(data{12}).*125e-9;
AP_ETime = double(data{13}).*125e-9;
Tilt_Time = double(data{14}).*125e-9;
Mag_Time = double(data{15}).*125e-9;
GPS_Hdr = cellstr(data{16});
UTC_Time = double(data{17});
Latitude = strjust(num2str(double(data{18})),'left');
Latitude = DMS_2_DD(str2num(Latitude(:,1:2)),str2num(Latitude(:,3:end)),0);
N_S = cellstr(data{19});
Longitude = strjust(num2str(double(data{20})),'left');
Longitude = DMS_2_DD(str2num(Longitude(:,1:3)),str2num(Longitude(:,4:end)),0);
E_W = cellstr(data{21});
Fix_Type = double(data{22});
Satellites = double(data{23});
HDOP = double(data{24});
MSL_Alt = double(data{25});
MSL_Units = cellstr(data{26});
Geoid_Sep = double(data{27});
Geoid_Units = cellstr(data{28});
Age_of_Corr = double(data{29});
Checksum = char(data{30});
Checksum = hex2dec(Checksum(:,2:3));
220
function [D,M,S] = DD_2_DMS(deg)
%Decimal Degrees to Degrees, Minutes, Seconds
%[D,M,S] = DD_2_DMS(deg)
%
%Authored By: Doug Bowlus 24 Oct. 2007
if deg >= 0
MS = mod(deg,1);
D = deg - MS;
M = (MS - mod(MS,(1./60))).*60;
S = ((MS.*60) - M) .* 60;
else
deg = abs(deg);
MS = mod(deg,1);
D = (deg - MS) .* -1;
M = (MS - mod(MS,(1./60))).*60;
S = ((MS.*60) - M) .* 60;
End
function [DD] = DMS_2_DD(deg,min,sec)
%Degrees, Minutes, Seconds to Decimal Degrees
%[DD] = DMS_2_DD(deg,min,sec)
%
%Authored By: Doug Bowlus 24 Oct. 2007
if deg >= 0
DD = deg + (min./60) + (sec./60./60);
else
DD = deg - (min./60) - (sec./60./60);
End
function [X,Y,Z,Z2] = WGS84_2_Cart(lat,long,hp)
%WGS84 to Cartesian Coordinates transformation function
%[X,Y,Z] = WGS84_2_Cart(lat,long,ht)
%
%North = Positive Latitude, South = Negative Latitude
%East = Positive Longitude, West = Negative Longitude
%Authored By: Doug Bowlus 24 Oct. 2007
%
%X,Y,Z in meters
%WGS84 Parameters
a = 6378137.0; %Semi-Major Axis in meters
b = 6356752.3142; %Semi-Minor Axis
ecc = 0.00669437999013; %Eccentricity squared
flat = 1.0./298.257223563; %Flattening f = (a-b)/a
221
%Perform conversion
vp = a ./ (1.0-ecc .* sind(lat).^2).^(1/2);
X = (vp + hp) .* cosd(lat) .* cosd(long);
Y = (vp + hp) .* cosd(lat) .* sind(long);
Z = (vp .* (1.0-ecc) + hp) .* sind(lat);
%Heading Data Analysis Script
clear all
clc
close all
%Load Calibration File and Computer Calibration Parameters
filename = 'LOG3.TXT';
known_heading = 165.6;
[Xos,Yos,Xrange,Yrange,RF] = MagCalibrate(filename,known_heading);
%Load Data File
filename = 'LOG10.TXT';
known_heading = 144;
[OS_Hdr,Time,X_Mag,Y_Mag,Z_Mag,X_Tilt,Y_Tilt] = importosdata(filename);
Heading = Mag2Heading(X_Mag,Y_Mag,Xos,Yos,Xrange,Yrange,RF);
error = known_heading - Heading;
Time = Time - Time(1);
subplot(2,1,1)
hold on
plot(Time,Heading,'b')
plot(Time,known_heading.*ones(length(Time)),'r')
hold off
grid on
title('Heading Vs. Time')
xlabel('Elapsed Time (seconds)')
ylabel('Heading (degrees)')
legend('Measured Heading','Gyro Heading')
subplot(2,1,2)
plot(Time,error,'k')
grid on
title('Heading Error Vs. Time')
xlabel('Elapsed Time (seconds)')
ylabel('Heading Error (degrees)')
avg_heading = mean(Heading)
avg_error = mean(error)
std_heading = std(Heading)
duration = Time(end) - Time(1)
% RF1 = 178.1 - 191 = -12.9
% RF2 = 179.4 - 190 = -10.6
% RF3 = 165.6 - 203.2 = -37.6
%
%
%
%
%
%
%
%
figure
plot(X_Mag,'r')
hold on
grid on
plot(Y_Mag,'b')
plot(Z_Mag,'k')
plot(Heading,'m')
legend('X','Y','Z','Heading')
% OUTPUT GRAPHS
he1 = [.39 .28 .12 -.10 -.42 -.75 -.50 -.09 -0.12 0.21 0.45 0.27 -0.4 -1.23 -0.62];
he2 = [-0.44 -0.56 -0.57 -0.46 -0.33 -0.28 0.12 0.36 -.1 -.23 -.32 -.61 -1.22 -1.95
-1.37];
he3 = [.41 .5 .58 .58 .44 .19 .40 .65 .37 .43 .44 .11 -.62 -1.4 -.73];
val = 0:24:336;
222
%
% figure
% plot(val,he1,'ro-')
% hold on
% grid on
% plot(val,he2,'bo-')
% plot(val,he3,'ko-')
% legend('Calibration 1','Calibration 2','Calibration 3')
% title('Mean Heading Error Vs. Heading')
% ylabel('Mean Heading Error (degrees)')
% xlabel('Heading (degrees)')
%
sd1 = [.18 .13 .14 .12 .12 .11 .11 .13 .14 .13 .11 .1 .09 .1 .12 .15 .01 .13 .12
.14 .11 .18 .1 .12];
sd2 = [.18 .13 .13 .12 .12 .11 .11 .14 .15 .13 .11 .1 .09 .1 .12 .15 .1 .13 .12 .14
.11 .19 .1 .12];
sd3 = [.18 .13 .13 .12 .12 .11 .11 .14 .15 .13 .11 .1 .09 .1 .12 .15 .1 .13 .12 .14
.11 .18 .1 .12];
%
% figure
% %plot(val,sd1(1:15),'ro-')
% hold on
% grid on
% plot(val,sd2(1:15),'ko-')
% %plot(val,sd3(1:15),'ko-')
% %legend('Calibration 1','Calibration 2','Calibration 3')
% title('Standard Deviation Vs. Heading')
% ylabel('Standard Deviation (degrees)')
% xlabel('Heading (degrees)')
OMHE1
OMHE2
OMHE3
OMSD1
OMSD2
OMSD3
=
=
=
=
=
=
mean(he1)
mean(he2)
mean(he3)
mean(sd1)
mean(sd2)
mean(sd3)
function [OS_Hdr,Time,X_Mag,Y_Mag,Z_Mag,X_Tilt,Y_Tilt] = importosdata(filename)
%
%importuwgps
%
%Authored by Doug Bowlus on 12/27/2007
%
223
%[OS_Hdr,Time,X_Mag,Y_Mag,Z_Mag,X_Tilt_Y_Tilt] = importosdata(filename)
%
%Given the filename for OSSEN log data, this script imports all of it into
%appropriate variable names
%
fid = fopen(filename);
data = textscan(fid,'%s%f%f%f%f%f%f',-1,'delimiter',',');
OS_Hdr = cellstr(data{1});
Time = double(data{2}) .* 125e-9;
X_Mag = double(data{3});
Y_Mag = double(data{4});
Z_Mag = double(data{5});
X_Tilt = double(data{6})./10;
Y_Tilt = double(data{7})./10;
224
function [Xos,Yos,Xrange,Yrange,RF] = MagCalibrate(filename,known_heading)
[OS_Hdr,Time,X_Mag,Y_Mag,Z_Mag,X_Tilt,Y_Tilt] = importosdata(filename);
%Calibrate Magnetometer Heading according to PNI Multipoint
%Primer Application Note. Assumes imported data comes from
%magnetometer being rotated in a circle. The known heading
%of the unit at the start of the collected data. A gyro or
%be used to obtain this value.
Xmax = max(X_Mag);
Xmin = min(X_Mag);
Ymax = max(Y_Mag);
Ymin = min(Y_Mag);
Calibration
the
is the heading
other means can
Xos = (Xmax + Xmin)./2;
Yos = (Ymax + Ymin)./2;
Xrange = (Xmax - Xmin);
Yrange = (Ymax - Ymin);
[Heading] = Mag2Heading(X_Mag,Y_Mag,Xos,Yos,Xrange,Yrange,0);
RF = known_heading - mean(Heading(1:10)); %Use the average of the first 10 points
to compute the rotation
function [Heading] = Mag2Heading(X_Mag,Y_Mag,Xos,Yos,Xrange,Yrange,RF)
%
%Heading = Mag2Heading(Xvalue,Yvalue,Xos,Yos,Xrange,Yrange,RF)
%
%Authored by Doug Bowlus on 1/27/2007
%
%Turns raw magnetometer values into a heading given the parameters
%from calibration. RF = Rotation Factor
%
Xvalue = X_Mag - Xos;
Yvalue = Y_Mag - Yos;
if Xrange > Yrange
Yvalue = (Yvalue .* Xrange) ./ Yrange;
else
Xvalue = (Xvalue .* Yrange) ./ Xrange;
end
Heading = (atan2(Yvalue,Xvalue) .* (180./pi));
for u = 1:length(Heading), %Compensate for -180 to 0 headings
if Heading(u) < 0
%Makes these headings 180 to 360
Heading(u) = 360 + Heading(u);
end
end
Heading = Heading + RF;
%Rotate the headings for proper north orientation
for u = 1:length(Heading), %Make headings ly between 0 - 360 after rotation
if Heading(u) >= 360
Heading(u) = Heading(u) - 360;
elseif Heading(u) < 0
Heading(u) = Heading(u) + 360;
end
end
225
%Tilt Test Data Processing Script
%Authored by Doug Bowlus on 1/31/2008
clear all
clc
close all
%Calibration Values
XCal = -1.19 - (-0.0766); %F180 Neg Roll Value - Avg Xtilt (values from log1.txt
test. Reference Level
YCal = 2.89 - 2.7641; %F180 Pitch Value - Avg Ytilt (values from log1.txt test.
Reference Level
%Load Data File
filename = 'LOG10.TXT';
known_xtilt = 2.79; %Negative Roll
known_ytilt = 2.94; %Pitch
[OS_Hdr,Time,X_Mag,Y_Mag,Z_Mag,X_Tilt,Y_Tilt] = importosdata(filename);
%Apply Calibration Values
X_Tilt = X_Tilt + XCal;
Y_Tilt = Y_Tilt + YCal;
Time = Time - Time(1);
xerror = known_xtilt - X_Tilt;
yerror = known_ytilt - Y_Tilt;
%X TILT PLOTS
subplot(2,1,1)
hold on
plot(Time,X_Tilt,'b')
plot(Time,known_xtilt.*ones(length(Time)),'r')
hold off
grid on
title('X Tilt Vs. Time')
xlabel('Elapsed Time (seconds)')
ylabel('X Tilt (degrees)')
legend('Measured X Tilt','F180 Tilt')
subplot(2,1,2)
plot(Time,xerror,'k')
grid on
title('X Tilt Error Vs. Time')
xlabel('Elapsed Time (seconds)')
ylabel('X Tilt Error (degrees)')
%Y TILT PLOTS
figure
subplot(2,1,1)
hold on
plot(Time,Y_Tilt,'b')
plot(Time,known_ytilt.*ones(length(Time)),'r')
hold off
grid on
title('Y Tilt Vs. Time')
xlabel('Elapsed Time (seconds)')
ylabel('Y Tilt (degrees)')
legend('Measured Y Tilt','F180 Tilt')
subplot(2,1,2)
plot(Time,yerror,'k')
grid on
title('Y Tilt Error Vs. Time')
xlabel('Elapsed Time (seconds)')
ylabel('Y Tilt Error (degrees)')
226
avg_x = mean(X_Tilt)
avg_y = mean(Y_Tilt)
avg_xerror = mean(xerror)
avg_yerror = mean(yerror)
std_xtilt = std(X_Tilt)
std_ytilt = std(Y_Tilt)
duration = Time(end) - Time(1)
%Create Plots of processed data
xe = [-.27 -.32 -.44 -.6 .28 .45 .45 .05 .18 .05 .08 .16 .13 -.1 -.05 -0.02]; %X
Error
xsd = [0.21 .25 .24 .26 .24 .21 .3 .3 .36 .32 .35 .31 .29 .32 .25 .22]; %X Standard
Deviation
ye = [.02 .02 -.06 .08 .04 -.1 -.03 .1 -.16 -.14 -.32 -.38 .34 .43 .23 -0.03]; %Y
Error
ysd = [.27 .27 .28 .31 .26 .34 .34 .33 .37 .36 .3 .28 .27 .28 .27 .25];% Y Standard
Deviation
xa = [-1.22 -1.5 -1.42 -1.71 -.89 -.75 -1.32 -.83 2.79 7.74 12.85 20.36 -17.50 23.04 -11.56 -1.26]; %X Angles
ya = [-5.32 -9.12 -14.29 -21.25 11.8 18.18 23.48 7.46 2.94 2.83 2.77 2.74 2.93 3.08
2.84 2.82]; %Y Angles
%Pick out pertinent test data
[xa1,I] = sort(xa(9:16));
xe1 = xe(9:16);
xe1 = xe1(I);
xsd1 = xsd(9:16);
xsd1 = xsd1(I);
[ya1,I] = sort([ya(1:8) ya(16)]);
ye1 = [ye(1:8) ye(16)];
ye1 = ye1(I);
ysd1 = [ysd(1:8) ysd(16)];
ysd1 = ysd1(I);
% %Plot Error and Standard Deviation
% figure
% plot(xa1,xe1,'ro-')
% hold on
% grid on
% plot(ya1,ye1,'bo-')
% axis([-25 25 -.25 .25])
% legend('X-Axis','Y-Axis')
% title('Mean Tilt Error Vs. Tilt Angle')
% ylabel('Mean Tilt Error (degrees)')
% xlabel('Tilt Angle (degrees)')
%
% figure
% plot(xa1,xsd1,'ro-')
% hold on
% grid on
% plot(ya1,ysd1,'bo-')
% axis([-25 25 0 .4])
% legend('X-Axis','Y-Axis')
% title('Standard Deviation Vs. Tilt Angle')
% ylabel('Standard Deviation (degrees)')
% xlabel('Tilt Angle (degrees)')
%Test Data Statistics
OMXE = mean(xe1)
OMYE = mean(ye1)
OMXSD = mean(xsd1)
OMYSD = mean(ysd1)
227
Appendix E: Supporting Test Documents
228
229
230
231
232
233
234
235
236
237
238