[Olsr-dev] =? ?q?=5BPATCH=20v1=203/5=5D=20PUD=3A=20include=20nmealib=20v0=2E6=2E6-1-gbfff65b?=

Ferry Huberts (spam-protected)
Thu May 10 16:09:59 CEST 2012


From: Ferry Huberts <(spam-protected)>

Signed-off-by: Ferry Huberts <(spam-protected)>
---
 lib/pud/{wireformat => nmealib}/.gitignore         |    0
 lib/pud/nmealib/LICENSE.TXT                        |  502 +++++++++++++++++++
 lib/pud/nmealib/Makefile                           |   81 +++
 lib/pud/nmealib/Makefile.inc                       |   39 ++
 lib/pud/nmealib/README.TXT                         |   33 ++
 lib/pud/nmealib/doc/.gitignore                     |    5 +
 lib/pud/nmealib/doc/Makefile                       |   18 +
 .../{doc/doxygen.conf => nmealib/doc/nmea.doxygen} |   10 +-
 lib/pud/nmealib/include/nmea/config.h              |   34 ++
 lib/pud/nmealib/include/nmea/context.h             |   51 ++
 lib/pud/nmealib/include/nmea/generate.h            |   52 ++
 lib/pud/nmealib/include/nmea/generator.h           |   89 ++++
 lib/pud/nmealib/include/nmea/gmath.h               |  102 ++++
 lib/pud/nmealib/include/nmea/info.h                |  132 +++++
 lib/pud/nmealib/include/nmea/nmea.h                |   37 ++
 lib/pud/nmealib/include/nmea/parse.h               |   50 ++
 lib/pud/nmealib/include/nmea/parser.h              |   69 +++
 lib/pud/nmealib/include/nmea/sentence.h            |  139 ++++++
 lib/pud/nmealib/include/nmea/time.h                |   54 ++
 lib/pud/nmealib/include/nmea/tok.h                 |   38 ++
 lib/pud/nmealib/include/nmea/units.h               |   38 ++
 lib/pud/nmealib/include/nmea/util.h                |   37 ++
 lib/pud/nmealib/samples/Makefile                   |   44 ++
 lib/pud/nmealib/samples/generate/main.c            |   69 +++
 lib/pud/nmealib/samples/generator/main.c           |   55 +++
 lib/pud/nmealib/samples/math/main.c                |   97 ++++
 lib/pud/nmealib/samples/parse/main.c               |   58 +++
 lib/pud/nmealib/samples/parse_file/gpslog.txt      |  311 ++++++++++++
 lib/pud/nmealib/samples/parse_file/main.c          |   93 ++++
 lib/pud/nmealib/src/context.c                      |   78 +++
 lib/pud/nmealib/src/generate.c                     |  237 +++++++++
 lib/pud/nmealib/src/generator.c                    |  412 ++++++++++++++++
 lib/pud/nmealib/src/gmath.c                        |  379 +++++++++++++++
 lib/pud/nmealib/src/info.c                         |  347 +++++++++++++
 lib/pud/nmealib/src/parse.c                        |  513 ++++++++++++++++++++
 lib/pud/nmealib/src/parser.c                       |  419 ++++++++++++++++
 lib/pud/nmealib/src/sentence.c                     |   64 +++
 lib/pud/nmealib/src/time.c                         |   41 ++
 lib/pud/nmealib/src/tok.c                          |  270 ++++++++++
 lib/pud/nmealib/src/util.c                         |   85 ++++
 40 files changed, 5177 insertions(+), 5 deletions(-)
 copy lib/pud/{wireformat => nmealib}/.gitignore (100%)
 create mode 100644 lib/pud/nmealib/LICENSE.TXT
 create mode 100644 lib/pud/nmealib/Makefile
 create mode 100644 lib/pud/nmealib/Makefile.inc
 create mode 100644 lib/pud/nmealib/README.TXT
 create mode 100644 lib/pud/nmealib/doc/.gitignore
 create mode 100644 lib/pud/nmealib/doc/Makefile
 copy lib/pud/{doc/doxygen.conf => nmealib/doc/nmea.doxygen} (99%)
 create mode 100644 lib/pud/nmealib/include/nmea/config.h
 create mode 100644 lib/pud/nmealib/include/nmea/context.h
 create mode 100644 lib/pud/nmealib/include/nmea/generate.h
 create mode 100644 lib/pud/nmealib/include/nmea/generator.h
 create mode 100644 lib/pud/nmealib/include/nmea/gmath.h
 create mode 100644 lib/pud/nmealib/include/nmea/info.h
 create mode 100644 lib/pud/nmealib/include/nmea/nmea.h
 create mode 100644 lib/pud/nmealib/include/nmea/parse.h
 create mode 100644 lib/pud/nmealib/include/nmea/parser.h
 create mode 100644 lib/pud/nmealib/include/nmea/sentence.h
 create mode 100644 lib/pud/nmealib/include/nmea/time.h
 create mode 100644 lib/pud/nmealib/include/nmea/tok.h
 create mode 100644 lib/pud/nmealib/include/nmea/units.h
 create mode 100644 lib/pud/nmealib/include/nmea/util.h
 create mode 100644 lib/pud/nmealib/samples/Makefile
 create mode 100644 lib/pud/nmealib/samples/generate/main.c
 create mode 100644 lib/pud/nmealib/samples/generator/main.c
 create mode 100644 lib/pud/nmealib/samples/math/main.c
 create mode 100644 lib/pud/nmealib/samples/parse/main.c
 create mode 100644 lib/pud/nmealib/samples/parse_file/gpslog.txt
 create mode 100644 lib/pud/nmealib/samples/parse_file/main.c
 create mode 100644 lib/pud/nmealib/src/context.c
 create mode 100644 lib/pud/nmealib/src/generate.c
 create mode 100644 lib/pud/nmealib/src/generator.c
 create mode 100644 lib/pud/nmealib/src/gmath.c
 create mode 100644 lib/pud/nmealib/src/info.c
 create mode 100644 lib/pud/nmealib/src/parse.c
 create mode 100644 lib/pud/nmealib/src/parser.c
 create mode 100644 lib/pud/nmealib/src/sentence.c
 create mode 100644 lib/pud/nmealib/src/time.c
 create mode 100644 lib/pud/nmealib/src/tok.c
 create mode 100644 lib/pud/nmealib/src/util.c

diff --git a/lib/pud/wireformat/.gitignore b/lib/pud/nmealib/.gitignore
similarity index 100%
copy from lib/pud/wireformat/.gitignore
copy to lib/pud/nmealib/.gitignore
diff --git a/lib/pud/nmealib/LICENSE.TXT b/lib/pud/nmealib/LICENSE.TXT
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/lib/pud/nmealib/LICENSE.TXT
@@ -0,0 +1,502 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/lib/pud/nmealib/Makefile b/lib/pud/nmealib/Makefile
new file mode 100644
index 0000000..6ba877a
--- /dev/null
+++ b/lib/pud/nmealib/Makefile
@@ -0,0 +1,81 @@
+include Makefile.inc
+
+#
+# Settings
+#
+
+LIBNAME = libnmea.so
+
+DESTDIR ?=
+
+MACHINE=$(shell uname -m)
+ifeq ($(strip $(MACHINE)),x86_64)
+LIBDIR = usr/lib64
+else
+LIBDIR = usr/lib
+endif
+INCLUDEDIR = usr/include
+
+MODULES = context generate generator gmath info parse parser sentence time tok util
+OBJ = $(MODULES:%=build/%.o)
+
+LIBS = -lm
+INCS = -I ./include
+
+
+#
+# Targets
+#
+
+all: all-before lib/$(LIBNAME)
+
+remake: clean all
+
+lib/$(LIBNAME): $(OBJ)
+	@echo "[LD] $@"
+	@$(CC) -shared -Wl,-soname=$(LIBNAME) -o lib/$(LIBNAME) $(OBJ) -lc
+
+build/%.o: src/%.c Makefile Makefile.inc
+	@echo "[CC] $<"
+	@$(CC) $(CCFLAGS) $(INCS) -c $< -o $@
+
+samples: all
+	$(MAKE) -C samples all
+
+
+#
+# Phony Targets
+#
+
+.PHONY: all-before clean doc install install-headers uninstall uninstall-headers
+
+all-before:
+	@mkdir -p build lib
+
+clean:
+	$(MAKE) -C doc clean
+	$(MAKE) -C samples clean
+	rm -fr build lib
+
+doc:
+	$(MAKE) -C doc all
+
+install: all
+	@mkdir -v -p "$(DESTDIR)/$(LIBDIR)"
+	cp "lib/$(LIBNAME)" "$(DESTDIR)/$(LIBDIR)/$(LIBNAME).$(VERSION)"
+	$(STRIP) "$(DESTDIR)/$(LIBDIR)/$(LIBNAME).$(VERSION)"
+	ldconfig -n "$(DESTDIR)/$(LIBDIR)"
+
+install-headers: all
+	@mkdir -v -p "$(DESTDIR)/$(INCLUDEDIR)"
+	@rm -fr "$(DESTDIR)/$(INCLUDEDIR)/nmea"
+	cp -r include/nmea "$(DESTDIR)/$(INCLUDEDIR)"
+
+uninstall:
+	rm -f "$(DESTDIR)/$(LIBDIR)/$(LIBNAME)" "$(DESTDIR)/$(LIBDIR)/$(LIBNAME).$(VERSION)"
+	ldconfig -n "$(DESTDIR)/$(LIBDIR)"
+	@rmdir -v -p --ignore-fail-on-non-empty "$(DESTDIR)/$(LIBDIR)"
+
+uninstall-headers:
+	rm -fr "$(DESTDIR)/$(INCLUDEDIR)/nmea"
+	@rmdir -v -p --ignore-fail-on-non-empty "$(DESTDIR)/$(INCLUDEDIR)"
diff --git a/lib/pud/nmealib/Makefile.inc b/lib/pud/nmealib/Makefile.inc
new file mode 100644
index 0000000..98ee50d
--- /dev/null
+++ b/lib/pud/nmealib/Makefile.inc
@@ -0,0 +1,39 @@
+######################
+#
+# Highlevel configuration options for all
+#
+#
+
+# activate debugging with 1 or deactivate with 0
+DEBUG ?= 1
+
+
+######################
+#
+# Lowlevel options and rules
+#
+
+ifeq ($(DEBUG),0)
+STRIP ?=	strip
+else
+STRIP ?=	:
+endif
+
+
+GITVERSION = $(shell git describe --dirty='-dirty')
+
+# we expect the version to be like 'v0.5.3-27-g0c2727a' and then strip the 'v',
+# and the '-27-g0c2727a' parts
+VERSION=$(shell git describe | \
+          sed -r -e 's/^([^[:digit:]]+)(.*)/\2/' \
+                 -e 's/^([^-]+)(.*)/\1/' | \
+          grep -E '[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+')
+
+# protect against no version number
+ifeq ($(strip $(VERSION)),)
+VERSION=0.0.0
+endif
+
+CC ?= gcc
+CCFLAGS += -fPIC -O2 -Wall -Wextra -Wformat=2 -Winit-self \
+           -Wmissing-include-dirs -Wswitch-default -Wswitch-enum -Werror
diff --git a/lib/pud/nmealib/README.TXT b/lib/pud/nmealib/README.TXT
new file mode 100644
index 0000000..f24bc87
--- /dev/null
+++ b/lib/pud/nmealib/README.TXT
@@ -0,0 +1,33 @@
+NMEA library
+
+Disclaimer
+
+The National Marine Electronics Association (NMEA) has developed a specification
+that defines the interface between various pieces of marine electronic
+equipment. The standard permits marine electronics to send information to
+computers and to other marine equipment.
+
+Most computer programs that provide real time position information understand
+and expect data to be in NMEA format. This data includes the complete PVT
+(position, velocity, time) solution computed by the GPS receiver. The idea of
+NMEA is to send a line of data called a sentence that is totally self contained
+and independent from other sentences. All NMEA sentences are sequences of ACSII
+symbols that begin with a '$' and end with a carriage return/line feed sequence
+and can be no longer than 80 characters of visible text (plus the line
+terminators).
+
+Introduction
+
+Features
+
+- Analysis NMEA sentences and granting GPS data in C structures
+- Generate NMEA sentences
+- Supported sentences: GPGGA, GPGSA, GPGSV, GPRMC, GPVTG
+- Multilevel architecture of algorithms
+- Additional functions of geographical mathematics and work with navigation data
+
+Supported (tested) platforms
+
+- Linux (GCC)
+
+Licence: LGPL
diff --git a/lib/pud/nmealib/doc/.gitignore b/lib/pud/nmealib/doc/.gitignore
new file mode 100644
index 0000000..447bc4d
--- /dev/null
+++ b/lib/pud/nmealib/doc/.gitignore
@@ -0,0 +1,5 @@
+/html/
+/latex/
+/man/
+/nmealib.pdf
+/nmea.doxygen.temp
diff --git a/lib/pud/nmealib/doc/Makefile b/lib/pud/nmealib/doc/Makefile
new file mode 100644
index 0000000..81a5118
--- /dev/null
+++ b/lib/pud/nmealib/doc/Makefile
@@ -0,0 +1,18 @@
+include ../Makefile.inc
+
+.PHONY: all clean
+
+clean:
+	rm -fr html latex man nmealib.pdf
+
+all: clean nmea.doxygen
+	@echo "Updating version..."
+	@sed -r "s/^([[:space:]]*PROJECT_NUMBER[[:space:]]*=).*/\1 $(GITVERSION)/" nmea.doxygen > nmea.doxygen.temp
+	@echo "Generating HTML and man pages..."
+	@doxygen nmea.doxygen.temp
+	@rm nmea.doxygen.temp
+	@echo "Generating PDF..."
+	@make -C latex -s > /dev/null 2>&1
+	@mv latex/refman.pdf nmealib.pdf
+	@rm -fr latex
+	@echo "Done"
diff --git a/lib/pud/doc/doxygen.conf b/lib/pud/nmealib/doc/nmea.doxygen
similarity index 99%
copy from lib/pud/doc/doxygen.conf
copy to lib/pud/nmealib/doc/nmea.doxygen
index f3ecc07..5ae8c60 100644
--- a/lib/pud/doc/doxygen.conf
+++ b/lib/pud/nmealib/doc/nmea.doxygen
@@ -25,13 +25,13 @@ DOXYFILE_ENCODING      = UTF-8
 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded
 # by quotes) that should identify the project.
 
-PROJECT_NAME           = "__LIBNAME__"
+PROJECT_NAME           = "NMEAlib"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = "__PLUGIN_VER__"
+PROJECT_NUMBER         =
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
 # base path where the generated documentation will be put.
@@ -581,7 +581,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = ../src
+INPUT                  = ../src ../include/nmea
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -908,7 +908,7 @@ GENERATE_HTMLHELP      = NO
 # can add a path in front of the file if the result should not be
 # written to the html output directory.
 
-CHM_FILE               = __LIBNAME__.chm
+CHM_FILE               = nmealib.chm
 
 # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
 # be used to specify the location (absolute path including file name) of
@@ -1122,7 +1122,7 @@ COMPACT_LATEX          = NO
 # by the printer. Possible values are: a4, a4wide, letter, legal and
 # executive. If left blank a4wide will be used.
 
-PAPER_TYPE             = a4
+PAPER_TYPE             = a4wide
 
 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
 # packages that should be included in the LaTeX output.
diff --git a/lib/pud/nmealib/include/nmea/config.h b/lib/pud/nmealib/include/nmea/config.h
new file mode 100644
index 0000000..915c4fb
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/config.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_CONFIG_H__
+#define __NMEA_CONFIG_H__
+
+#define NMEA_POSIX(x)  (x)
+#define NMEA_INLINE    inline
+
+#if !defined(NDEBUG)
+#include <assert.h>
+#define NMEA_ASSERT(x)   assert(x)
+#else
+#define NMEA_ASSERT(x)
+#endif
+
+#endif /* __NMEA_CONFIG_H__ */
diff --git a/lib/pud/nmealib/include/nmea/context.h b/lib/pud/nmealib/include/nmea/context.h
new file mode 100644
index 0000000..c692a86
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/context.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_CONTEXT_H__
+#define __NMEA_CONTEXT_H__
+
+#define NMEA_DEF_PARSEBUFF  (1024)
+#define NMEA_MIN_PARSEBUFF  (256)
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef void (*nmeaTraceFunc)(const char *str, int str_size);
+typedef void (*nmeaErrorFunc)(const char *str, int str_size);
+
+typedef struct _nmeaPROPERTY {
+	nmeaTraceFunc trace_func;
+	nmeaErrorFunc error_func;
+	int parse_buff_size;
+
+} nmeaPROPERTY;
+
+nmeaPROPERTY * nmea_property(void);
+
+void nmea_trace(const char *str, ...);
+void nmea_trace_buff(const char *buff, int buff_size);
+void nmea_error(const char *str, ...);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_CONTEXT_H__ */
diff --git a/lib/pud/nmealib/include/nmea/generate.h b/lib/pud/nmealib/include/nmea/generate.h
new file mode 100644
index 0000000..34eab4e
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/generate.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_GENERATE_H__
+#define __NMEA_GENERATE_H__
+
+#include <nmea/info.h>
+#include <nmea/sentence.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+int nmea_generate(char *buff, int buff_sz, const nmeaINFO *info,
+		int generate_mask);
+
+int nmea_gen_GPGGA(char *buff, int buff_sz, nmeaGPGGA *pack);
+int nmea_gen_GPGSA(char *buff, int buff_sz, nmeaGPGSA *pack);
+int nmea_gen_GPGSV(char *buff, int buff_sz, nmeaGPGSV *pack);
+int nmea_gen_GPRMC(char *buff, int buff_sz, nmeaGPRMC *pack);
+int nmea_gen_GPVTG(char *buff, int buff_sz, nmeaGPVTG *pack);
+
+void nmea_info2GPGGA(const nmeaINFO *info, nmeaGPGGA *pack);
+void nmea_info2GPGSA(const nmeaINFO *info, nmeaGPGSA *pack);
+void nmea_info2GPRMC(const nmeaINFO *info, nmeaGPRMC *pack);
+void nmea_info2GPVTG(const nmeaINFO *info, nmeaGPVTG *pack);
+
+int nmea_gsv_npack(int sat_count);
+void nmea_info2GPGSV(const nmeaINFO *info, nmeaGPGSV *pack, int pack_idx);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_GENERATE_H__ */
diff --git a/lib/pud/nmealib/include/nmea/generator.h b/lib/pud/nmealib/include/nmea/generator.h
new file mode 100644
index 0000000..6d7c049
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/generator.h
@@ -0,0 +1,89 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_GENERATOR_H__
+#define __NMEA_GENERATOR_H__
+
+#include <nmea/info.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * high level
+ */
+
+struct _nmeaGENERATOR;
+
+enum nmeaGENTYPE
+{
+    NMEA_GEN_NOISE = 0,
+    NMEA_GEN_STATIC,
+    NMEA_GEN_ROTATE,
+
+    NMEA_GEN_SAT_STATIC,
+    NMEA_GEN_SAT_ROTATE,
+    NMEA_GEN_POS_RANDMOVE,
+
+    NMEA_GEN_LAST
+};
+
+struct _nmeaGENERATOR * nmea_create_generator(int type, nmeaINFO *info);
+void    nmea_destroy_generator(struct _nmeaGENERATOR *gen);
+
+int     nmea_generate_from(
+        char *buff, int buff_sz,    /* buffer */
+        nmeaINFO *info,             /* source info */
+        struct _nmeaGENERATOR *gen, /* generator */
+        int generate_mask           /* mask of sentence`s (e.g. GPGGA | GPGSA) */
+        );
+
+/*
+ * low level
+ */
+
+typedef int (*nmeaNMEA_GEN_INIT)(struct _nmeaGENERATOR *gen, nmeaINFO *info);
+typedef int (*nmeaNMEA_GEN_LOOP)(struct _nmeaGENERATOR *gen, nmeaINFO *info);
+typedef int (*nmeaNMEA_GEN_RESET)(struct _nmeaGENERATOR *gen, nmeaINFO *info);
+typedef int (*nmeaNMEA_GEN_DESTROY)(struct _nmeaGENERATOR *gen);
+
+typedef struct _nmeaGENERATOR
+{
+    void                *gen_data;
+    nmeaNMEA_GEN_INIT    init_call;
+    nmeaNMEA_GEN_LOOP    loop_call;
+    nmeaNMEA_GEN_RESET   reset_call;
+    nmeaNMEA_GEN_DESTROY destroy_call;
+    struct _nmeaGENERATOR *next;
+
+} nmeaGENERATOR;
+
+int     nmea_gen_init(nmeaGENERATOR *gen, nmeaINFO *info);
+int     nmea_gen_loop(nmeaGENERATOR *gen, nmeaINFO *info);
+int     nmea_gen_reset(nmeaGENERATOR *gen, nmeaINFO *info);
+void    nmea_gen_destroy(nmeaGENERATOR *gen);
+void    nmea_gen_add(nmeaGENERATOR *to, nmeaGENERATOR *gen);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_GENERATOR_H__ */
diff --git a/lib/pud/nmealib/include/nmea/gmath.h b/lib/pud/nmealib/include/nmea/gmath.h
new file mode 100644
index 0000000..5bd37d9
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/gmath.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_GMATH_H__
+#define __NMEA_GMATH_H__
+
+#include <nmea/info.h>
+
+#define NMEA_PI                     (3.141592653589793)             /**< PI value */
+#define NMEA_PI180                  (NMEA_PI / 180)                 /**< PI division by 180 */
+#define NMEA_EARTHRADIUS_KM         (6378)                          /**< Earth's mean radius in km */
+#define NMEA_EARTHRADIUS_M          (NMEA_EARTHRADIUS_KM * 1000)    /**< Earth's mean radius in m */
+#define NMEA_EARTH_SEMIMAJORAXIS_M  (6378137.0)                     /**< Earth's semi-major axis in m according WGS84 */
+#define NMEA_EARTH_SEMIMAJORAXIS_KM (NMEA_EARTHMAJORAXIS_KM / 1000) /**< Earth's semi-major axis in km according WGS 84 */
+#define NMEA_EARTH_FLATTENING       (1 / 298.257223563)             /**< Earth's flattening according WGS 84 */
+#define NMEA_DOP_FACTOR             (5)                             /**< Factor for translating DOP to meters */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * degree VS radian
+ */
+
+double nmea_degree2radian(double val);
+double nmea_radian2degree(double val);
+
+/*
+ * NDEG (NMEA degree)
+ */
+
+double nmea_ndeg2degree(double val);
+double nmea_degree2ndeg(double val);
+
+double nmea_ndeg2radian(double val);
+double nmea_radian2ndeg(double val);
+
+/*
+ * DOP
+ */
+
+double nmea_calc_pdop(double hdop, double vdop);
+double nmea_dop2meters(double dop);
+double nmea_meters2dop(double meters);
+
+/*
+ * positions work
+ */
+
+void nmea_info2pos(const nmeaINFO *info, nmeaPOS *pos);
+void nmea_pos2info(const nmeaPOS *pos, nmeaINFO *info);
+
+double  nmea_distance(
+        const nmeaPOS *from_pos,
+        const nmeaPOS *to_pos
+        );
+
+double  nmea_distance_ellipsoid(
+        const nmeaPOS *from_pos,
+        const nmeaPOS *to_pos,
+        double *from_azimuth,
+        double *to_azimuth
+        );
+
+int     nmea_move_horz(
+        const nmeaPOS *start_pos,
+        nmeaPOS *end_pos,
+        double azimuth,
+        double distance
+        );
+
+int     nmea_move_horz_ellipsoid(
+        const nmeaPOS *start_pos,
+        nmeaPOS *end_pos,
+        double azimuth,
+        double distance,
+        double *end_azimuth
+        );
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_GMATH_H__ */
diff --git a/lib/pud/nmealib/include/nmea/info.h b/lib/pud/nmealib/include/nmea/info.h
new file mode 100644
index 0000000..ce74e80
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/info.h
@@ -0,0 +1,132 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \file */
+
+#ifndef __NMEA_INFO_H__
+#define __NMEA_INFO_H__
+
+#include <nmea/time.h>
+#include <stdbool.h>
+
+#define NMEA_SIG_BAD   (0)
+#define NMEA_SIG_LOW   (1)
+#define NMEA_SIG_MID   (2)
+#define NMEA_SIG_HIGH  (3)
+
+#define NMEA_FIX_BAD   (1)
+#define NMEA_FIX_2D    (2)
+#define NMEA_FIX_3D    (3)
+
+#define NMEA_MAXSAT    (12)
+#define NMEA_SATINPACK (4)
+#define NMEA_NSATPACKS (NMEA_MAXSAT / NMEA_SATINPACK)
+
+#define NMEA_DEF_LAT   (5001.2621)
+#define NMEA_DEF_LON   (3613.0595)
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Position data in fractional degrees or radians
+ */
+typedef struct _nmeaPOS {
+	double lat; /**< Latitude */
+	double lon; /**< Longitude */
+
+} nmeaPOS;
+
+/**
+ * Information about satellite
+ * @see nmeaSATINFO
+ * @see nmeaGPGSV
+ */
+typedef struct _nmeaSATELLITE {
+	int id;      /**< Satellite PRN number */
+	int in_use;  /**< Used in position fix */
+	int elv;     /**< Elevation in degrees, 90 maximum */
+	int azimuth; /**< Azimuth, degrees from true north, 000 to 359 */
+	int sig;     /**< Signal, 00-99 dB */
+
+} nmeaSATELLITE;
+
+/**
+ * Information about all satellites in view
+ * @see nmeaINFO
+ * @see nmeaGPGSV
+ */
+typedef struct _nmeaSATINFO {
+	int inuse;  /**< Number of satellites in use (not those in view) */
+	int inview; /**< Total number of satellites in view */
+	nmeaSATELLITE sat[NMEA_MAXSAT]; /**< Satellites information */
+
+} nmeaSATINFO;
+
+/**
+ * Summary GPS information from all parsed packets,
+ * used also for generating NMEA stream
+ * @see nmea_parse
+ * @see nmea_GPGGA2info,  nmea_...2info
+ */
+typedef struct _nmeaINFO {
+	int smask;    /**< Mask specifying from which sentences data has been obtained */
+
+	nmeaTIME utc; /**< UTC of position */
+
+	int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
+	int fix; /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */
+
+	double PDOP;        /**< Position Dilution Of Precision */
+	double HDOP;        /**< Horizontal Dilution Of Precision */
+	double VDOP;        /**< Vertical Dilution Of Precision */
+
+	double lat;         /**< Latitude in NDEG - +/-[degree][min].[sec/60] */
+	double lon;         /**< Longitude in NDEG - +/-[degree][min].[sec/60] */
+	double elv;         /**< Antenna altitude above/below mean sea level (geoid) in meters */
+	double speed;       /**< Speed over the ground in kilometers/hour */
+	double direction;   /**< Track angle in degrees True */
+	double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */
+
+	nmeaSATINFO satinfo; /**< Satellites information */
+} nmeaINFO;
+
+/**
+ * Enumeration for the fields names of a nmeaINFO structure
+ */
+typedef enum _nmeaINFO_FIELD {
+	SMASK, UTC, SIG, FIX, PDOP, HDOP, VDOP, LAT, LON, ELV, SPEED, DIRECTION,
+	DECLINATION, SATINFO
+} nmeaINFO_FIELD;
+
+void nmea_zero_INFO(nmeaINFO *info);
+
+bool nmea_INFO_has_field(int smask, nmeaINFO_FIELD fieldName);
+
+void nmea_INFO_sanitise(nmeaINFO *nmeaInfo);
+
+void nmea_INFO_unit_conversion(nmeaINFO * nmeaInfo);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_INFO_H__ */
diff --git a/lib/pud/nmealib/include/nmea/nmea.h b/lib/pud/nmealib/include/nmea/nmea.h
new file mode 100644
index 0000000..c761579
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/nmea.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_H__
+#define __NMEA_H__
+
+#include <nmea/config.h>
+#include <nmea/context.h>
+#include <nmea/generate.h>
+#include <nmea/generator.h>
+#include <nmea/gmath.h>
+#include <nmea/info.h>
+#include <nmea/parse.h>
+#include <nmea/parser.h>
+#include <nmea/sentence.h>
+#include <nmea/time.h>
+#include <nmea/tok.h>
+#include <nmea/units.h>
+
+#endif /* __NMEA_H__ */
diff --git a/lib/pud/nmealib/include/nmea/parse.h b/lib/pud/nmealib/include/nmea/parse.h
new file mode 100644
index 0000000..adfe406
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/parse.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_PARSE_H__
+#define __NMEA_PARSE_H__
+
+#include <nmea/info.h>
+#include <nmea/sentence.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+int nmea_pack_type(const char *buff, int buff_sz);
+int nmea_find_tail(const char *buff, int buff_sz, int *res_crc);
+
+int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack);
+int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack);
+int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack);
+int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack);
+int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack);
+
+void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info);
+void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info);
+void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info);
+void nmea_GPRMC2info(nmeaGPRMC *pack, nmeaINFO *info);
+void nmea_GPVTG2info(nmeaGPVTG *pack, nmeaINFO *info);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_PARSE_H__ */
diff --git a/lib/pud/nmealib/include/nmea/parser.h b/lib/pud/nmealib/include/nmea/parser.h
new file mode 100644
index 0000000..94d71c8
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/parser.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_PARSER_H__
+#define __NMEA_PARSER_H__
+
+#include <nmea/info.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * high level
+ */
+
+typedef struct _nmeaPARSER
+{
+    void *top_node;
+    void *end_node;
+    unsigned char *buffer;
+    int buff_size;
+    int buff_use;
+
+} nmeaPARSER;
+
+int     nmea_parser_init(nmeaPARSER *parser);
+void    nmea_parser_destroy(nmeaPARSER *parser);
+
+int     nmea_parse(
+        nmeaPARSER *parser,
+        const char *buff, int buff_sz,
+        nmeaINFO *info
+        );
+
+/*
+ * low level
+ */
+
+int     nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz);
+int     nmea_parser_top(nmeaPARSER *parser);
+int     nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr);
+int     nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr);
+int     nmea_parser_drop(nmeaPARSER *parser);
+int     nmea_parser_buff_clear(nmeaPARSER *parser);
+int     nmea_parser_queue_clear(nmeaPARSER *parser);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_PARSER_H__ */
diff --git a/lib/pud/nmealib/include/nmea/sentence.h b/lib/pud/nmealib/include/nmea/sentence.h
new file mode 100644
index 0000000..8f36272
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/sentence.h
@@ -0,0 +1,139 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \file */
+
+#ifndef __NMEA_SENTENCE_H__
+#define __NMEA_SENTENCE_H__
+
+#include <nmea/info.h>
+#include <nmea/time.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/**
+ * NMEA packets type which parsed and generated by library
+ */
+enum nmeaPACKTYPE
+{
+    GPNON   = 0x0000,   /**< Unknown packet type. */
+    GPGGA   = 0x0001,   /**< GGA - Essential fix data which provide 3D location and accuracy data. */
+    GPGSA   = 0x0002,   /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */
+    GPGSV   = 0x0004,   /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */
+    GPRMC   = 0x0008,   /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */
+    GPVTG   = 0x0010    /**< VTG - Actual track made good and speed over ground. */
+};
+
+/**
+ * GGA packet information structure (Global Positioning System Fix Data)
+ */
+typedef struct _nmeaGPGGA
+{
+    nmeaTIME utc;       /**< UTC of position (just time) */
+	double  lat;        /**< Latitude in NDEG - [degree][min].[sec/60] */
+    char    ns;         /**< [N]orth or [S]outh */
+	double  lon;        /**< Longitude in NDEG - [degree][min].[sec/60] */
+    char    ew;         /**< [E]ast or [W]est */
+    int     sig;        /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
+	int     satinuse;   /**< Number of satellites in use (not those in view) */
+    double  HDOP;       /**< Horizontal dilution of precision */
+    double  elv;        /**< Antenna altitude above/below mean sea level (geoid) */
+    char    elv_units;  /**< [M]eters (Antenna height unit) */
+    double  diff;       /**< Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level. '-' = geoid is below WGS-84 ellipsoid) */
+    char    diff_units; /**< [M]eters (Units of geoidal separation) */
+    double  dgps_age;   /**< Time in seconds since last DGPS update */
+    int     dgps_sid;   /**< DGPS station ID number */
+
+} nmeaGPGGA;
+
+/**
+ * GSA packet information structure (Satellite status)
+ */
+typedef struct _nmeaGPGSA
+{
+    char    fix_mode;   /**< Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D) */
+    int     fix_type;   /**< Type, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */
+    int     sat_prn[NMEA_MAXSAT]; /**< PRNs of satellites used in position fix (null for unused fields) */
+    double  PDOP;       /**< Dilution of precision */
+    double  HDOP;       /**< Horizontal dilution of precision */
+    double  VDOP;       /**< Vertical dilution of precision */
+
+} nmeaGPGSA;
+
+/**
+ * GSV packet information structure (Satellites in view)
+ */
+typedef struct _nmeaGPGSV
+{
+    int     pack_count; /**< Total number of messages of this type in this cycle */
+    int     pack_index; /**< Message number */
+    int     sat_count;  /**< Total number of satellites in view */
+    nmeaSATELLITE sat_data[NMEA_SATINPACK];
+
+} nmeaGPGSV;
+
+/**
+ * RMC packet information structure (Recommended Minimum sentence C)
+ */
+typedef struct _nmeaGPRMC
+{
+    nmeaTIME utc;       /**< UTC of position */
+    char    status;     /**< Status (A = active or V = void) */
+	double  lat;        /**< Latitude in NDEG - [degree][min].[sec/60] */
+    char    ns;         /**< [N]orth or [S]outh */
+	double  lon;        /**< Longitude in NDEG - [degree][min].[sec/60] */
+    char    ew;         /**< [E]ast or [W]est */
+    double  speed;      /**< Speed over the ground in knots */
+    double  direction;  /**< Track angle in degrees True */
+    double  declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */
+    char    declin_ew;  /**< [E]ast or [W]est */
+    char    mode;       /**< Mode indicator of fix type (A = autonomous, D = differential, E = estimated, N = not valid, S = simulator) */
+
+} nmeaGPRMC;
+
+/**
+ * VTG packet information structure (Track made good and ground speed)
+ */
+typedef struct _nmeaGPVTG
+{
+    double  dir;        /**< True track made good (degrees) */
+    char    dir_t;      /**< Fixed text 'T' indicates that track made good is relative to true north */
+    double  dec;        /**< Magnetic track made good */
+    char    dec_m;      /**< Fixed text 'M' */
+    double  spn;        /**< Ground speed, knots */
+    char    spn_n;      /**< Fixed text 'N' indicates that speed over ground is in knots */
+    double  spk;        /**< Ground speed, kilometers per hour */
+    char    spk_k;      /**< Fixed text 'K' indicates that speed over ground is in kilometers/hour */
+
+} nmeaGPVTG;
+
+void nmea_zero_GPGGA(nmeaGPGGA *pack);
+void nmea_zero_GPGSA(nmeaGPGSA *pack);
+void nmea_zero_GPGSV(nmeaGPGSV *pack);
+void nmea_zero_GPRMC(nmeaGPRMC *pack);
+void nmea_zero_GPVTG(nmeaGPVTG *pack);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_SENTENCE_H__ */
diff --git a/lib/pud/nmealib/include/nmea/time.h b/lib/pud/nmealib/include/nmea/time.h
new file mode 100644
index 0000000..9e6666d
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/time.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \file */
+
+#ifndef __NMEA_TIME_H__
+#define __NMEA_TIME_H__
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Date and time data
+ * @see nmea_time_now
+ */
+typedef struct _nmeaTIME {
+	int year; /**< Years since 1900 */
+	int mon;  /**< Months since January - [0,11] */
+	int day;  /**< Day of the month - [1,31] */
+	int hour; /**< Hours since midnight - [0,23] */
+	int min;  /**< Minutes after the hour - [0,59] */
+	int sec;  /**< Seconds after the minute - [0,59] */
+	int hsec; /**< Hundredth part of second - [0,99] */
+
+} nmeaTIME;
+
+/**
+ * \brief Get time now to nmeaTIME structure
+ */
+void nmea_time_now(nmeaTIME *t);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_TIME_H__ */
diff --git a/lib/pud/nmealib/include/nmea/tok.h b/lib/pud/nmealib/include/nmea/tok.h
new file mode 100644
index 0000000..e132d68
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/tok.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_TOK_H__
+#define __NMEA_TOK_H__
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+int nmea_calc_crc(const char *buff, int buff_sz);
+int nmea_atoi(const char *str, int str_sz, int radix);
+double nmea_atof(const char *str, int str_sz);
+int nmea_printf(char *buff, int buff_sz, const char *format, ...);
+int nmea_scanf(const char *buff, int buff_sz, const char *format, ...);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_TOK_H__ */
diff --git a/lib/pud/nmealib/include/nmea/units.h b/lib/pud/nmealib/include/nmea/units.h
new file mode 100644
index 0000000..ebc717a
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/units.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_UNITS_H__
+#define __NMEA_UNITS_H__
+
+/*
+ * Distance units
+ */
+
+#define NMEA_TUD_YARDS (1.0936) /**< Yards, meter * NMEA_TUD_YARDS = yard */
+#define NMEA_TUD_KNOTS (1.852)  /**< Knots, kilometer / NMEA_TUD_KNOTS = knot */
+#define NMEA_TUD_MILES (1.609)  /**< Miles, kilometer / NMEA_TUD_MILES = mile */
+
+/*
+ * Speed units
+ */
+
+#define NMEA_TUS_MS    (3.6)    /**< Meters per seconds, (k/h) / NMEA_TUS_MS= (m/s) */
+
+#endif /* __NMEA_UNITS_H__ */
diff --git a/lib/pud/nmealib/include/nmea/util.h b/lib/pud/nmealib/include/nmea/util.h
new file mode 100644
index 0000000..f3b0f6d
--- /dev/null
+++ b/lib/pud/nmealib/include/nmea/util.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NMEA_UTIL_H__
+#define __NMEA_UTIL_H__
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+bool nmea_string_has_invalid_chars(const char * str, const char * strName,
+		char * report, size_t reportSize);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __NMEA_UTIL_H__ */
diff --git a/lib/pud/nmealib/samples/Makefile b/lib/pud/nmealib/samples/Makefile
new file mode 100644
index 0000000..a583a20
--- /dev/null
+++ b/lib/pud/nmealib/samples/Makefile
@@ -0,0 +1,44 @@
+include ../Makefile.inc
+
+#
+# Settings
+#
+
+SAMPLES = generate generator math parse parse_file
+SMPLS = $(SAMPLES:%=../build/samples/%)
+SMPLOBJ = $(SAMPLES:%=%/main.o)
+
+LIBS = -lm -L../lib -lnmea
+INCS = -I ../include
+
+
+#
+# Targets
+#
+
+all: all-before samples
+
+remake: clean all
+
+samples: $(SMPLS)
+
+../build/samples/%: %/main.o
+	@echo "[LD] $@"
+	@$(CC) $(CCFLAGS) $< $(LIBS) -o $@
+
+%/main.o: %/main.c Makefile ../Makefile.inc
+	@echo "[CC] $<"
+	@$(CC) $(CCFLAGS) $(INCS) -c $< -o $@
+
+
+#
+# Phony Targets
+#
+
+.PHONY: all-before clean
+
+all-before:
+	@mkdir -p ../build/samples
+
+clean:
+	rm -f $(SMPLOBJ) $(SMPLS)
diff --git a/lib/pud/nmealib/samples/generate/main.c b/lib/pud/nmealib/samples/generate/main.c
new file mode 100644
index 0000000..73e584d
--- /dev/null
+++ b/lib/pud/nmealib/samples/generate/main.c
@@ -0,0 +1,69 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/nmea.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+int main()
+{
+    nmeaINFO info;
+    char buff[2048];
+    int gen_sz;
+    int it;
+
+    nmea_zero_INFO(&info);
+
+    info.sig = 3;
+    info.fix = 3;
+    info.lat = 5000.0;
+    info.lon = 3600.0;
+    info.speed = 2.14 * NMEA_TUS_MS;
+    info.elv = 10.86;
+
+    info.satinfo.inuse = 1;
+    info.satinfo.inview = 1;
+
+    /*
+    info.satinfo.sat[0].id = 1;
+    info.satinfo.sat[0].in_use = 1;
+    info.satinfo.sat[0].elv = 50;
+    info.satinfo.sat[0].azimuth = 0;
+    info.satinfo.sat[0].sig = 99;
+    */
+
+    for(it = 0; it < 10; ++it)
+    {
+        gen_sz = nmea_generate(
+            &buff[0], 2048, &info,
+            GPGGA | GPGSA | GPGSV | GPRMC | GPVTG
+            );
+
+        buff[gen_sz] = 0;
+        printf("%s\n", &buff[0]);
+
+        usleep(500000);
+
+        info.speed += .1;
+    }
+
+    return 0;
+}
diff --git a/lib/pud/nmealib/samples/generator/main.c b/lib/pud/nmealib/samples/generator/main.c
new file mode 100644
index 0000000..f95cf1e
--- /dev/null
+++ b/lib/pud/nmealib/samples/generator/main.c
@@ -0,0 +1,55 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/nmea.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+int main()
+{
+    nmeaGENERATOR *gen;
+    nmeaINFO info;
+    char buff[2048];
+    int gen_sz;
+    int it;
+
+    nmea_zero_INFO(&info);
+
+    if(0 == (gen = nmea_create_generator(NMEA_GEN_ROTATE, &info)))
+        return -1;
+
+    for(it = 0; it < 10000; ++it)
+    {
+        gen_sz = nmea_generate_from(
+            &buff[0], 2048, &info, gen,
+            GPGGA | GPGSA | GPGSV | GPRMC | GPVTG
+            );
+
+        buff[gen_sz] = 0;
+        printf("%s\n", &buff[0]);
+
+        usleep(500000);        
+    }
+
+    nmea_gen_destroy(gen);
+
+    return 0;
+}
diff --git a/lib/pud/nmealib/samples/math/main.c b/lib/pud/nmealib/samples/math/main.c
new file mode 100644
index 0000000..d1bcfa8
--- /dev/null
+++ b/lib/pud/nmealib/samples/math/main.c
@@ -0,0 +1,97 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/nmea.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#define NUM_POINTS 4
+
+int main()
+{
+    const char *buff[] = {
+        "$GPRMC,213916.199,A,4221.0377,N,07102.9778,W,0.00,,010207,,,A*6A\r\n",
+        "$GPRMC,213917.199,A,4221.0510,N,07102.9549,W,0.23,175.43,010207,,,A*77\r\n",
+        "$GPRMC,213925.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*68\r\n",
+        "$GPRMC,111609.14,A,5001.27,N,3613.06,E,11.2,0.0,261206,0.0,E*50\r\n"
+    };
+
+    nmeaPOS pos[NUM_POINTS], pos_moved[NUM_POINTS][2];
+    double dist[NUM_POINTS][2]; 
+    double azimuth[NUM_POINTS][2], azimuth_moved[NUM_POINTS];
+    int result[2];
+    int it = 0;
+
+    nmeaPARSER parser;
+    nmea_parser_init(&parser);
+
+    for(it = 0; it < NUM_POINTS; ++it)
+    {
+        nmeaINFO info;
+        nmea_zero_INFO(&info);
+        (void)nmea_parse(&parser, buff[it], (int)strlen(buff[it]), &info);
+        nmea_info2pos(&info, &pos[it]);
+    }
+
+    nmea_parser_destroy(&parser);
+
+    for(it = 0; it < NUM_POINTS; ++it)
+    {
+        dist[it][0] = nmea_distance(&pos[0], &pos[it]);
+        dist[it][1] = nmea_distance_ellipsoid(
+            &pos[0], &pos[it], &azimuth[it][0], &azimuth[it][1]
+            );
+    }
+
+    for(it = 0; it < NUM_POINTS; ++it)
+    {
+        result[0] = nmea_move_horz(&pos[0], &pos_moved[it][0], azimuth[it][0], dist[it][0]);
+        result[1] = nmea_move_horz_ellipsoid(
+            &pos[0], &pos_moved[it][1], azimuth[it][0], dist[it][0], &azimuth_moved[it]
+            );
+
+    }
+
+    /* Output of results */
+    printf("Coordinate points:\n");
+    for(it = 0; it < NUM_POINTS; ++it)
+    {
+        printf(
+            "P%d in radians: lat:%9.6lf lon:%9.6lf  \tin degree: lat:%+010.6lf° lon:%+011.6lf°\n",
+            it, pos[it].lat, pos[it].lon, nmea_radian2degree(pos[it].lat), nmea_radian2degree(pos[it].lon)
+            );
+    }
+
+    printf("\nCalculation results:\n");
+    for(it = 0; it < NUM_POINTS; ++it)
+    {
+        printf("\n");
+        printf("Distance P0 to P%d\ton spheroid:  %14.3lf m\n", it, dist[it][0]);
+        printf("Distance P0 to P%d\ton ellipsoid: %14.3lf m\n", it, dist[it][1]);
+        printf("Azimuth  P0 to P%d\tat start: %8.3lf°\tat end: %8.3lf°\n", it, nmea_radian2degree(azimuth[it][0]), nmea_radian2degree(azimuth[it][1]));
+        printf("Move     P0 to P%d\t         \tAzimuth at end: %8.3lf°\n", it, nmea_radian2degree(azimuth_moved[it]));
+        printf("Move     P0 to P%d\ton spheroid:  %3s lat:%+010.6lf° lon:%+011.6lf°\n", it, result[0] == 1 ? "OK" : "nOK", nmea_radian2degree(pos_moved[it][0].lat), nmea_radian2degree(pos_moved[it][0].lon));
+        printf("Move     P0 to P%d\ton ellipsoid: %3s lat:%+010.6lf° lon:%+011.6lf°\n", it, result[0] == 1 ? "OK" : "nOK", nmea_radian2degree(pos_moved[it][1].lat), nmea_radian2degree(pos_moved[it][1].lon));
+        printf("Move     P0 to P%d\toriginal:         lat:%+010.6lf° lon:%+011.6lf°\n", it, nmea_radian2degree(pos[it].lat), nmea_radian2degree(pos[it].lon));
+    }
+
+    return 0;
+}
diff --git a/lib/pud/nmealib/samples/parse/main.c b/lib/pud/nmealib/samples/parse/main.c
new file mode 100644
index 0000000..3f03da8
--- /dev/null
+++ b/lib/pud/nmealib/samples/parse/main.c
@@ -0,0 +1,58 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/nmea.h>
+
+#include <stdio.h>
+#include <string.h>
+
+int main()
+{
+    const char *buff[] = {
+        "$GPRMC,173843,A,3349.896,N,11808.521,W,000.0,360.0,230108,013.4,E*69\r\n",
+        "$GPGGA,111609.14,5001.27,N,3613.06,E,3,08,0.0,10.2,M,0.0,M,0.0,0000*70\r\n",
+        "$GPGSV,2,1,08,01,05,005,80,02,05,050,80,03,05,095,80,04,05,140,80*7f\r\n",
+        "$GPGSV,2,2,08,05,05,185,80,06,05,230,80,07,05,275,80,08,05,320,80*71\r\n",
+        "$GPGSA,A,3,01,02,03,04,05,06,07,08,00,00,00,00,0.0,0.0,0.0*3a\r\n",
+        "$GPRMC,111609.14,A,5001.27,N,3613.06,E,11.2,0.0,261206,0.0,E*50\r\n",
+        "$GPVTG,217.5,T,208.8,M,000.00,N,000.01,K*4C\r\n"
+    };
+
+    int it;
+    nmeaINFO info;
+    nmeaPARSER parser;
+    nmeaPOS dpos;
+
+    nmea_zero_INFO(&info);
+    nmea_parser_init(&parser);
+
+    for(it = 0; it < 6; ++it)
+    {
+        nmea_parse(&parser, buff[it], (int)strlen(buff[it]), &info);
+
+        nmea_info2pos(&info, &dpos);
+        printf("%03d, Lat: %f, Lon: %f, Sig: %d, Fix: %d\n", it, dpos.lat,
+               dpos.lon, info.sig, info.fix);
+    }
+
+    nmea_parser_destroy(&parser);
+
+    return 0;
+}
diff --git a/lib/pud/nmealib/samples/parse_file/gpslog.txt b/lib/pud/nmealib/samples/parse_file/gpslog.txt
new file mode 100644
index 0000000..f6086da
--- /dev/null
+++ b/lib/pud/nmealib/samples/parse_file/gpslog.txt
@@ -0,0 +1,311 @@
+$PSRFTXTVersion GSW3.2.1PAT_3.1.00.12-SDK001P1.00c *3F
+$PSRFTXTHTC GPS_ART_321000_GEN*20
+$PSRFTXTTOW:  258712*32
+$PSRFTXTWK:   1412*4F
+$PSRFTXTPOS:  1518885 -4470072 4274168*24
+$PSRFTXTCLK:  94817*02
+$PSRFTXTCHNL: 12*5F
+$PSRFTXTBaud rate: 57600 *51
+$GPGGA,213638.949,,,,,0,00,,,M,0.0,M,,0000*5F
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213638.949,V,,,,,,,010207,,,N*40
+$GPGGA,213639.897,,,,,0,00,,,M,0.0,M,,0000*5C
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213639.897,V,,,,,,,010207,,,N*43
+$GPGGA,213640.886,,,,,0,00,,,M,0.0,M,,0000*52
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213640.886,V,,,,,,,010207,,,N*4D
+$GPGGA,213641.886,,,,,0,00,,,M,0.0,M,,0000*53
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213641.886,V,,,,,,,010207,,,N*4C
+$GPGGA,213642.897,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79
+$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79
+$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78
+$GPRMC,213642.897,V,,,,,,,010207,,,N*4F
+$GPGGA,213643.886,,,,,0,00,,,M,0.0,M,,0000*51
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213643.886,V,,,,,,,010207,,,N*4E
+$GPGGA,213644.886,,,,,0,00,,,M,0.0,M,,0000*56
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213644.886,V,,,,,,,010207,,,N*49
+$GPGGA,213645.897,,,,,0,00,,,M,0.0,M,,0000*57
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213645.897,V,,,,,,,010207,,,N*48
+$GPGGA,213646.886,,,,,0,00,,,M,0.0,M,,0000*54
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213646.886,V,,,,,,,010207,,,N*4B
+$GPGGA,213647.886,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79
+$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79
+$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78
+$GPRMC,213647.886,V,,,,,,,010207,,,N*4A
+$GPGGA,213648.897,,,,,0,00,,,M,0.0,M,,0000*5A
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213648.897,V,,,,,,,010207,,,N*45
+$GPGGA,213649.886,,,,,0,00,,,M,0.0,M,,0000*5B
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213649.886,V,,,,,,,010207,,,N*44
+$GPGGA,213650.886,,,,,0,00,,,M,0.0,M,,0000*53
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213650.886,V,,,,,,,010207,,,N*4C
+$GPGGA,213651.897,,,,,0,00,,,M,0.0,M,,0000*52
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213651.897,V,,,,,,,010207,,,N*4D
+$GPGGA,213652.886,,,,,0,00,,,M,0.0,M,,0000*51
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79
+$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79
+$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78
+$GPRMC,213652.886,V,,,,,,,010207,,,N*4E
+$GPGGA,213653.886,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213653.886,V,,,,,,,010207,,,N*4F
+$GPGGA,213654.898,,,,,0,00,,,M,0.0,M,,0000*58
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213654.898,V,,,,,,,010207,,,N*47
+$GPGGA,213655.886,,,,,0,00,,,M,0.0,M,,0000*56
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213655.886,V,,,,,,,010207,,,N*49
+$GPGGA,213656.886,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213656.886,V,,,,,,,010207,,,N*4A
+$GPGGA,213657.897,,,,,0,00,,,M,0.0,M,,0000*54
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79
+$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79
+$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78
+$GPRMC,213657.897,V,,,,,,,010207,,,N*4B
+$GPGGA,213658.886,,,,,0,00,,,M,0.0,M,,0000*5B
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213658.886,V,,,,,,,010207,,,N*44
+$GPGGA,213659.886,,,,,0,00,,,M,0.0,M,,0000*5A
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213659.886,V,,,,,,,010207,,,N*45
+$GPGGA,213700.880,,,,,0,00,,,M,0.0,M,,0000*51
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213700.880,V,,,,,,,010207,,,N*4E
+$GPGGA,213701.880,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213701.880,V,,,,,,,010207,,,N*4F
+$GPGGA,213702.880,,,,,0,00,,,M,0.0,M,,0000*53
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,,10,46,055,*70
+$GPGSV,3,2,10,06,41,282,,02,23,120,,21,21,303,,08,16,068,*73
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213702.880,V,,,,,,,010207,,,N*4C
+$GPGGA,213703.880,,,,,0,00,,,M,0.0,M,,0000*52
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213703.880,V,,,,,,,010207,,,N*4D
+$GPGGA,213704.880,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213704.880,V,,,,,,,010207,,,N*4A
+$GPGGA,213705.879,,,,,0,00,,,M,0.0,M,,0000*52
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213705.879,V,,,,,,,010207,,,N*4D
+$GPGGA,213706.879,,,,,0,00,,,M,0.0,M,,0000*51
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213706.879,V,,,,,,,010207,,,N*4E
+$GPGGA,213707.879,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,,10,46,055,*70
+$GPGSV,3,2,10,06,41,282,,02,23,120,,21,21,303,,08,16,068,*73
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213707.879,V,,,,,,,010207,,,N*4F
+$GPGGA,213708.879,,,,,0,00,,,M,0.0,M,,0000*5F
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213708.879,V,,,,,,,010207,,,N*40
+$GPGGA,213709.879,,,,,0,00,,,M,0.0,M,,0000*5E
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213709.879,V,,,,,,,010207,,,N*41
+$GPGGA,213710.879,,,,,0,00,,,M,0.0,M,,0000*56
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213710.879,V,,,,,,,010207,,,N*49
+$GPGGA,213711.879,,,,,0,00,,,M,0.0,M,,0000*57
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213711.879,V,,,,,,,010207,,,N*48
+$GPGGA,213712.879,,,,,0,00,,,M,0.0,M,,0000*54
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,,10,46,055,*70
+$GPGSV,3,2,10,06,41,282,,02,23,120,,21,21,303,,08,16,068,*73
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213712.879,V,,,,,,,010207,,,N*4B
+$GPGGA,213713.879,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213713.879,V,,,,,,,010207,,,N*4A
+$GPGGA,213714.879,,,,,0,00,,,M,0.0,M,,0000*52
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213714.879,V,,,,,,,010207,,,N*4D
+$GPGGA,213715.879,,,,,0,00,,,M,0.0,M,,0000*53
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213715.879,V,,,,,,,010207,,,N*4C
+$GPGGA,213716.879,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213716.879,V,,,,,,,010207,,,N*4F
+$GPGGA,213717.879,,,,,0,00,,,M,0.0,M,,0000*51
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,25,10,46,055,*77
+$GPGSV,3,2,10,06,41,282,35,02,23,120,,21,21,303,,08,16,068,*75
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213717.879,V,,,,,,,010207,,,N*4E
+$GPGGA,213718.879,,,,,0,00,,,M,0.0,M,,0000*5E
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213718.879,V,,,,,,,010207,,,N*41
+$GPGGA,213719.879,,,,,0,00,,,M,0.0,M,,0000*5F
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213719.879,V,,,,,,,010207,,,N*40
+$GPGGA,213720.879,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213720.879,V,,,,,,,010207,,,N*4A
+$GPGGA,213721.879,,,,,0,00,,,M,0.0,M,,0000*54
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213721.879,V,,,,,,,010207,,,N*4B
+$GPGGA,213722.879,,,,,0,00,,,M,0.0,M,,0000*57
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,31,10,46,055,*72
+$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213722.879,V,,,,,,,010207,,,N*48
+$GPGGA,213723.990,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213723.990,V,,,,,,,010207,,,N*4F
+$GPGGA,213724.990,,,,,0,00,,,M,0.0,M,,0000*57
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213724.990,V,,,,,,,010207,,,N*48
+$GPGGA,213725.990,,,,,0,00,,,M,0.0,M,,0000*56
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213725.990,V,,,,,,,010207,,,N*49
+$GPGGA,213726.990,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213726.990,V,,,,,,,010207,,,N*4A
+$GPGGA,213727.990,,,,,0,00,,,M,0.0,M,,0000*54
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,30,10,46,055,*73
+$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213727.990,V,,,,,,,010207,,,N*4B
+$GPGGA,213728.990,,,,,0,00,,,M,0.0,M,,0000*5B
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213728.990,V,,,,,,,010207,,,N*44
+$GPGGA,213729.990,,,,,0,00,,,M,0.0,M,,0000*5A
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213729.990,V,,,,,,,010207,,,N*45
+$GPGGA,213730.990,,,,,0,00,,,M,0.0,M,,0000*52
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213730.990,V,,,,,,,010207,,,N*4D
+$GPGGA,213731.990,,,,,0,00,,,M,0.0,M,,0000*53
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213731.990,V,,,,,,,010207,,,N*4C
+$GPGGA,213732.990,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,27,10,46,055,*75
+$GPGSV,3,2,10,06,41,282,35,02,23,120,,21,21,303,,08,16,068,*75
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213732.990,V,,,,,,,010207,,,N*4F
+$GPGGA,213733.990,,,,,0,00,,,M,0.0,M,,0000*51
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213733.990,V,,,,,,,010207,,,N*4E
+$GPGGA,213734.990,,,,,0,00,,,M,0.0,M,,0000*56
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213734.990,V,,,,,,,010207,,,N*49
+$GPGGA,213735.990,,,,,0,00,,,M,0.0,M,,0000*57
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213735.990,V,,,,,,,010207,,,N*48
+$GPGGA,213736.990,,,,,0,00,,,M,0.0,M,,0000*54
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213736.990,V,,,,,,,010207,,,N*4B
+$GPGGA,213737.990,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,28,10,46,055,*7A
+$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213737.990,V,,,,,,,010207,,,N*4A
+$GPGGA,213738.990,,,,,0,00,,,M,0.0,M,,0000*5A
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213738.990,V,,,,,,,010207,,,N*45
+$GPGGA,213739.990,,,,,0,00,,,M,0.0,M,,0000*5B
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213739.990,V,,,,,,,010207,,,N*44
+$GPGGA,213740.990,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213740.990,V,,,,,,,010207,,,N*4A
+$GPGGA,213741.990,,,,,0,00,,,M,0.0,M,,0000*54
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213741.990,V,,,,,,,010207,,,N*4B
+$GPGGA,213742.990,,,,,0,00,,,M,0.0,M,,0000*57
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,28,10,46,055,*7A
+$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74
+$GPGSV,3,3,10,27,10,042,,18,08,257,*7B
+$GPRMC,213742.990,V,,,,,,,010207,,,N*48
+$GPGGA,213743.990,,,,,0,00,,,M,0.0,M,,0000*56
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213743.990,V,,,,,,,010207,,,N*49
+$GPGGA,213744.990,,,,,0,00,,,M,0.0,M,,0000*51
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213744.990,V,,,,,,,010207,,,N*4E
+$GPGGA,213745.990,,,,,0,00,,,M,0.0,M,,0000*50
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213745.990,V,,,,,,,010207,,,N*4F
+$GPGGA,213746.990,,,,,0,00,,,M,0.0,M,,0000*53
+$PSRFTXTVersion GSW3.2.1PAT_3.1.00.12-SDK001P1.00c *3F
+$PSRFTXTHTC GPS_ART_321000_GEN*20
+$PSRFTXTTOW:  423546*3B
+$PSRFTXTWK:   1412*4F
+$PSRFTXTPOS:  1533096 -4464909 4274442*2A
+$PSRFTXTCLK:  94810*05
+$PSRFTXTCHNL: 12*5F
+$PSRFTXTBaud rate: 57600 *51
+$GPGGA,213912.270,,,,,0,00,,,M,0.0,M,,0000*59
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213912.270,V,,,,,,,010207,,,N*46
+$GPGGA,213913.211,,,,,0,00,,,M,0.0,M,,0000*5F
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213913.211,V,,,,,,,010207,,,N*40
+$GPGGA,213914.200,,,,,0,00,,,M,0.0,M,,0000*58
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213914.200,V,,,,,,,010207,,,N*47
+$GPGGA,213915.196,,,,,0,00,,,M,0.0,M,,0000*55
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+$GPRMC,213915.196,V,,,,,,,010207,,,N*4A
+$GPGGA,213916.199,4221.0377,N,07102.9778,W,1,03,13.4,-32.4,M,-33.7,M,,0000*45
+$GPGSA,A,2,26,07,06,,,,,,,,,,13.4,13.4,1.0*37
+$GPGSV,3,1,11,26,55,180,28,06,46,258,33,07,43,272,30,21,22,304,*77
+$GPGSV,3,2,11,24,83,061,,29,64,170,,10,45,056,,02,23,121,*7F
+$GPGSV,3,3,11,08,17,067,,27,10,041,,18,05,257,*4B
+$GPRMC,213916.199,A,4221.0377,N,07102.9778,W,0.00,,010207,,,A*6A
+$GPGGA,213917.199,4221.0510,N,07102.9549,W,1,04,3.9,-65.2,M,-33.7,M,,0000*7C
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A
+$GPRMC,213917.199,A,4221.0510,N,07102.9549,W,0.23,175.43,010207,,,A*77
+$GPGGA,213918.199,4221.0853,N,07102.9382,W,1,04,3.9,50.0,M,-33.7,M,,0000*51
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A
+$GPRMC,213918.199,A,4221.0853,N,07102.9382,W,0.95,326.55,010207,,,A*7D
+$GPGGA,213919.000,4221.0975,N,07102.9300,W,1,04,3.9,86.2,M,-33.7,M,,0000*57
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A
+$GPRMC,213919.000,A,4221.0975,N,07102.9300,W,0.55,332.53,010207,,,A*7D
+$GPGGA,213920.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6C
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A
+$GPRMC,213920.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6D
+$GPGGA,213921.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6D
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A
+$GPGSV,3,1,11,26,55,180,29,06,46,258,26,07,43,272,33,21,22,304,26*75
+$GPGSV,3,2,11,24,83,061,,29,64,170,,10,45,056,,02,23,121,*7F
+$GPGSV,3,3,11,08,17,067,28,27,10,041,,18,05,257,*41
+$GPRMC,213921.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6C
+$GPGGA,213922.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6E
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A
+$GPRMC,213922.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6F
+$GPGGA,213923.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6F
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A
+$GPRMC,213923.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6E
+$GPGGA,213924.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*68
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.0,3.9,1.0*3B
+$GPRMC,213924.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*69
+$GPGGA,213925.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*69
+$GPGSA,A,3,26,07,06,21,,,,,,,,,4.0,3.9,1.0*3B
+$GPRMC,213925.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*68
+$GPGGA,213926.000,4221.1112,N,07102.9177,W,1,04,3.9,136.5,M,-33.7,M,,0000*6C
+
+
diff --git a/lib/pud/nmealib/samples/parse_file/main.c b/lib/pud/nmealib/samples/parse_file/main.c
new file mode 100644
index 0000000..a6f3617
--- /dev/null
+++ b/lib/pud/nmealib/samples/parse_file/main.c
@@ -0,0 +1,93 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/nmea.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+void trace(const char *str, int str_size)
+{
+    printf("Trace: ");
+    write(1, str, str_size);
+    printf("\n");
+}
+void error(const char *str, int str_size)
+{
+    printf("Error: ");
+    write(1, str, str_size);
+    printf("\n");
+}
+
+int main()
+{
+    static const char * filename = "../../samples/parse_file/gpslog.txt";
+    nmeaINFO info;
+    nmeaPARSER parser;
+    FILE *file;
+    char buff[2048];
+    int size, it = 0;
+    nmeaPOS dpos;
+
+    file = fopen(filename, "rb");
+
+    if(!file) {
+        printf("Could not open file %s\n", filename);
+        return -1;
+    }
+
+    nmea_property()->trace_func = &trace;
+    nmea_property()->error_func = &error;
+
+    nmea_zero_INFO(&info);
+    nmea_parser_init(&parser);
+
+    /*
+    while(1)
+    {
+    */
+
+    while(!feof(file))
+    {
+        size = (int)fread(&buff[0], 1, 100, file);
+
+        nmea_parse(&parser, &buff[0], size, &info);
+
+        nmea_info2pos(&info, &dpos);
+
+        printf(
+            "%03d, Lat: %f, Lon: %f, Sig: %d, Fix: %d\n",
+            it++, dpos.lat, dpos.lon, info.sig, info.fix
+            );
+    }
+
+    fseek(file, 0, SEEK_SET);
+
+    /*
+    }
+    */
+
+    nmea_parser_destroy(&parser);
+    fclose(file);
+
+    return 0;
+}
diff --git a/lib/pud/nmealib/src/context.c b/lib/pud/nmealib/src/context.c
new file mode 100644
index 0000000..c49d66f
--- /dev/null
+++ b/lib/pud/nmealib/src/context.c
@@ -0,0 +1,78 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/context.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <nmea/config.h>
+
+nmeaPROPERTY * nmea_property()
+{
+    static nmeaPROPERTY prop = {
+        0, 0, NMEA_DEF_PARSEBUFF
+        };
+
+    return ∝
+}
+
+void nmea_trace(const char *str, ...)
+{
+    int size;
+    va_list arg_list;
+    char buff[NMEA_DEF_PARSEBUFF];
+    nmeaTraceFunc func = nmea_property()->trace_func;
+
+    if(func)
+    {
+        va_start(arg_list, str);
+        size = NMEA_POSIX(vsnprintf)(&buff[0], NMEA_DEF_PARSEBUFF - 1, str, arg_list);
+        va_end(arg_list);
+
+        if(size > 0)
+            (*func)(&buff[0], size);
+    }
+}
+
+void nmea_trace_buff(const char *buff, int buff_size)
+{
+    nmeaTraceFunc func = nmea_property()->trace_func;
+    if(func && buff_size)
+        (*func)(buff, buff_size);
+}
+
+void nmea_error(const char *str, ...)
+{
+    int size;
+    va_list arg_list;
+    char buff[NMEA_DEF_PARSEBUFF];
+    nmeaErrorFunc func = nmea_property()->error_func;
+
+    if(func)
+    {
+        va_start(arg_list, str);
+        size = NMEA_POSIX(vsnprintf)(&buff[0], NMEA_DEF_PARSEBUFF - 1, str, arg_list);
+        va_end(arg_list);
+
+        if(size > 0)
+            (*func)(&buff[0], size);
+    }
+}
diff --git a/lib/pud/nmealib/src/generate.c b/lib/pud/nmealib/src/generate.c
new file mode 100644
index 0000000..abbb98f
--- /dev/null
+++ b/lib/pud/nmealib/src/generate.c
@@ -0,0 +1,237 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/generate.h>
+
+#include <math.h>
+
+#include <nmea/tok.h>
+#include <nmea/units.h>
+
+int nmea_gen_GPGGA(char *buff, int buff_sz, nmeaGPGGA *pack)
+{
+    return nmea_printf(buff, buff_sz,
+        "$GPGGA,%02d%02d%02d.%02d,%09.4f,%C,%010.4f,%C,%1d,%02d,%03.1f,%03.1f,%C,%03.1f,%C,%03.1f,%04d",
+        pack->utc.hour, pack->utc.min, pack->utc.sec, pack->utc.hsec,
+        pack->lat, pack->ns, pack->lon, pack->ew,
+        pack->sig, pack->satinuse, pack->HDOP, pack->elv, pack->elv_units,
+        pack->diff, pack->diff_units, pack->dgps_age, pack->dgps_sid);
+}
+
+int nmea_gen_GPGSA(char *buff, int buff_sz, nmeaGPGSA *pack)
+{
+    return nmea_printf(buff, buff_sz,
+        "$GPGSA,%C,%1d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%02d,%03.1f,%03.1f,%03.1f",
+        pack->fix_mode, pack->fix_type,
+        pack->sat_prn[0], pack->sat_prn[1], pack->sat_prn[2], pack->sat_prn[3], pack->sat_prn[4], pack->sat_prn[5],
+        pack->sat_prn[6], pack->sat_prn[7], pack->sat_prn[8], pack->sat_prn[9], pack->sat_prn[10], pack->sat_prn[11],
+        pack->PDOP, pack->HDOP, pack->VDOP);
+}
+
+int nmea_gen_GPGSV(char *buff, int buff_sz, nmeaGPGSV *pack)
+{
+    return nmea_printf(buff, buff_sz,
+        "$GPGSV,%1d,%1d,%02d,"
+        "%02d,%02d,%03d,%02d,"
+        "%02d,%02d,%03d,%02d,"
+        "%02d,%02d,%03d,%02d,"
+        "%02d,%02d,%03d,%02d",
+        pack->pack_count, pack->pack_index + 1, pack->sat_count,
+        pack->sat_data[0].id, pack->sat_data[0].elv, pack->sat_data[0].azimuth, pack->sat_data[0].sig,
+        pack->sat_data[1].id, pack->sat_data[1].elv, pack->sat_data[1].azimuth, pack->sat_data[1].sig,
+        pack->sat_data[2].id, pack->sat_data[2].elv, pack->sat_data[2].azimuth, pack->sat_data[2].sig,
+        pack->sat_data[3].id, pack->sat_data[3].elv, pack->sat_data[3].azimuth, pack->sat_data[3].sig);
+}
+
+int nmea_gen_GPRMC(char *buff, int buff_sz, nmeaGPRMC *pack)
+{
+    return nmea_printf(buff, buff_sz,
+        "$GPRMC,%02d%02d%02d.%02d,%C,%09.4f,%C,%010.4f,%C,%03.1f,%03.1f,%02d%02d%02d,%03.1f,%C,%C",
+        pack->utc.hour, pack->utc.min, pack->utc.sec, pack->utc.hsec,
+        pack->status, pack->lat, pack->ns, pack->lon, pack->ew,
+        pack->speed, pack->direction,
+        pack->utc.day, pack->utc.mon + 1, pack->utc.year - 100,
+        pack->declination, pack->declin_ew, pack->mode);
+}
+
+int nmea_gen_GPVTG(char *buff, int buff_sz, nmeaGPVTG *pack)
+{
+    return nmea_printf(buff, buff_sz,
+        "$GPVTG,%.1f,%C,%.1f,%C,%.1f,%C,%.1f,%C",
+        pack->dir, pack->dir_t,
+        pack->dec, pack->dec_m,
+        pack->spn, pack->spn_n,
+        pack->spk, pack->spk_k);
+}
+
+void nmea_info2GPGGA(const nmeaINFO *info, nmeaGPGGA *pack)
+{
+    nmea_zero_GPGGA(pack);
+
+    pack->utc = info->utc;
+    pack->lat = fabs(info->lat);
+    pack->ns = ((info->lat > 0)?'N':'S');
+    pack->lon = fabs(info->lon);
+    pack->ew = ((info->lon > 0)?'E':'W');
+    pack->sig = info->sig;
+    pack->satinuse = info->satinfo.inuse;
+    pack->HDOP = info->HDOP;
+    pack->elv = info->elv;
+}
+
+void nmea_info2GPGSA(const nmeaINFO *info, nmeaGPGSA *pack)
+{
+    int it;
+
+    nmea_zero_GPGSA(pack);
+
+    pack->fix_type = info->fix;
+    pack->PDOP = info->PDOP;
+    pack->HDOP = info->HDOP;
+    pack->VDOP = info->VDOP;
+
+    for(it = 0; it < NMEA_MAXSAT; ++it)
+    {
+        pack->sat_prn[it] =
+            ((info->satinfo.sat[it].in_use)?info->satinfo.sat[it].id:0);
+    }
+}
+
+int nmea_gsv_npack(int sat_count)
+{
+    int pack_count = (int)ceil(((double)sat_count) / NMEA_SATINPACK);
+
+    if(0 == pack_count)
+        pack_count = 1;
+
+    return pack_count;
+}
+
+void nmea_info2GPGSV(const nmeaINFO *info, nmeaGPGSV *pack, int pack_idx)
+{
+    int sit, pit;
+
+    nmea_zero_GPGSV(pack);
+
+    pack->sat_count = (info->satinfo.inview <= NMEA_MAXSAT)?info->satinfo.inview:NMEA_MAXSAT;
+    pack->pack_count = nmea_gsv_npack(pack->sat_count);
+
+    if(pack->pack_count == 0)
+        pack->pack_count = 1;
+
+    if(pack_idx >= pack->pack_count)
+        pack->pack_index = pack_idx % pack->pack_count;
+    else
+        pack->pack_index = pack_idx;
+
+    for(pit = 0, sit = pack->pack_index * NMEA_SATINPACK; pit < NMEA_SATINPACK; ++pit, ++sit)
+        pack->sat_data[pit] = info->satinfo.sat[sit];
+}
+
+void nmea_info2GPRMC(const nmeaINFO *info, nmeaGPRMC *pack)
+{
+    nmea_zero_GPRMC(pack);
+
+    pack->utc = info->utc;
+    pack->status = ((info->sig > 0)?'A':'V');
+    pack->lat = fabs(info->lat);
+    pack->ns = ((info->lat > 0)?'N':'S');
+    pack->lon = fabs(info->lon);
+    pack->ew = ((info->lon > 0)?'E':'W');
+    pack->speed = info->speed / NMEA_TUD_KNOTS;
+    pack->direction = info->direction;
+    pack->declination = info->declination;
+    pack->declin_ew = 'E';
+    pack->mode = ((info->sig > 0)?'A':'N');
+}
+
+void nmea_info2GPVTG(const nmeaINFO *info, nmeaGPVTG *pack)
+{
+    nmea_zero_GPVTG(pack);
+
+    pack->dir = info->direction;
+    pack->dec = info->declination;
+    pack->spn = info->speed / NMEA_TUD_KNOTS;
+    pack->spk = info->speed;
+}
+
+int nmea_generate(
+    char *buff, int buff_sz,
+    const nmeaINFO *info,
+    int generate_mask
+    )
+{
+    int gen_count = 0, gsv_it, gsv_count;
+    int pack_mask = generate_mask;
+
+    nmeaGPGGA gga;
+    nmeaGPGSA gsa;
+    nmeaGPGSV gsv;
+    nmeaGPRMC rmc;
+    nmeaGPVTG vtg;
+
+    if(!buff)
+        return 0;
+
+    while(pack_mask)
+    {
+        if(pack_mask & GPGGA)
+        {
+            nmea_info2GPGGA(info, &gga);
+            gen_count += nmea_gen_GPGGA(buff + gen_count, buff_sz - gen_count, &gga);
+            pack_mask &= ~GPGGA;
+        }
+        else if(pack_mask & GPGSA)
+        {
+            nmea_info2GPGSA(info, &gsa);
+            gen_count += nmea_gen_GPGSA(buff + gen_count, buff_sz - gen_count, &gsa);
+            pack_mask &= ~GPGSA;
+        }
+        else if(pack_mask & GPGSV)
+        {
+            gsv_count = nmea_gsv_npack(info->satinfo.inview);
+            for(gsv_it = 0; gsv_it < gsv_count && buff_sz - gen_count > 0; ++gsv_it)
+            {
+                nmea_info2GPGSV(info, &gsv, gsv_it);
+                gen_count += nmea_gen_GPGSV(buff + gen_count, buff_sz - gen_count, &gsv);
+            }
+            pack_mask &= ~GPGSV;
+        }
+        else if(pack_mask & GPRMC)
+        {
+            nmea_info2GPRMC(info, &rmc);
+            gen_count += nmea_gen_GPRMC(buff + gen_count, buff_sz - gen_count, &rmc);
+            pack_mask &= ~GPRMC;
+        }
+        else if(pack_mask & GPVTG)
+        {
+            nmea_info2GPVTG(info, &vtg);
+            gen_count += nmea_gen_GPVTG(buff + gen_count, buff_sz - gen_count, &vtg);
+            pack_mask &= ~GPVTG;
+        }
+        else
+            break;
+
+        if(buff_sz - gen_count <= 0)
+            break;
+    }
+
+    return gen_count;
+}
diff --git a/lib/pud/nmealib/src/generator.c b/lib/pud/nmealib/src/generator.c
new file mode 100644
index 0000000..5cc2158
--- /dev/null
+++ b/lib/pud/nmealib/src/generator.c
@@ -0,0 +1,412 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/generator.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <nmea/context.h>
+#include <nmea/generate.h>
+#include <nmea/gmath.h>
+
+double nmea_random(double min, double max)
+{
+    static double rand_max = RAND_MAX;
+    double rand_val = rand();
+    double bounds = max - min;
+    return min + (rand_val * bounds) / rand_max;
+}
+
+/*
+ * low level
+ */
+
+int nmea_gen_init(nmeaGENERATOR *gen, nmeaINFO *info)
+{
+    int RetVal = 1; int smask = info->smask;
+    nmeaGENERATOR *igen = gen;
+
+    nmea_zero_INFO(info);
+    info->smask = smask;
+
+    info->lat = NMEA_DEF_LAT;
+    info->lon = NMEA_DEF_LON;
+
+    while(RetVal && igen)
+    {
+        if(igen->init_call)
+            RetVal = (*igen->init_call)(igen, info);
+        igen = igen->next;
+    }
+
+    return RetVal;
+}
+
+int nmea_gen_loop(nmeaGENERATOR *gen, nmeaINFO *info)
+{
+    int RetVal = 1;
+
+    if(gen->loop_call)
+        RetVal = (*gen->loop_call)(gen, info);
+
+    if(RetVal && gen->next)
+        RetVal = nmea_gen_loop(gen->next, info);
+
+    return RetVal;
+}
+
+int nmea_gen_reset(nmeaGENERATOR *gen, nmeaINFO *info)
+{
+    int RetVal = 1;
+
+    if(gen->reset_call)
+        RetVal = (*gen->reset_call)(gen, info);
+
+    return RetVal;
+}
+
+void nmea_gen_destroy(nmeaGENERATOR *gen)
+{
+    if(gen->next)
+    {
+        nmea_gen_destroy(gen->next);
+        gen->next = 0;
+    }
+
+    if(gen->destroy_call)
+        (*gen->destroy_call)(gen);
+
+    free(gen);
+}
+
+void nmea_gen_add(nmeaGENERATOR *to, nmeaGENERATOR *gen)
+{
+    if(to->next)
+        nmea_gen_add(to->next, gen);
+    else
+        to->next = gen;
+}
+
+int nmea_generate_from(
+    char *buff, int buff_sz,
+    nmeaINFO *info,
+    nmeaGENERATOR *gen,
+    int generate_mask
+    )
+{
+    int retval;
+
+    if(0 != (retval = nmea_gen_loop(gen, info)))
+        retval = nmea_generate(buff, buff_sz, info, generate_mask);
+
+    return retval;
+}
+
+/*
+ * NOISE generator
+ */
+
+int nmea_igen_noise_init(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info __attribute__ ((unused)))
+{
+    return 1;
+}
+
+int nmea_igen_noise_loop(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info)
+{
+    int it;
+    int in_use;
+
+    info->sig = (int)nmea_random(1, 3);
+    info->PDOP = nmea_random(0, 9);
+    info->HDOP = nmea_random(0, 9);
+    info->VDOP = nmea_random(0, 9);
+    info->fix = (int)nmea_random(2, 3);
+    info->lat = nmea_random(0, 100);
+    info->lon = nmea_random(0, 100);
+    info->speed = nmea_random(0, 100);
+    info->direction = nmea_random(0, 360);
+    info->declination = nmea_random(0, 360);
+    info->elv = (int)nmea_random(-100, 100);
+
+    info->satinfo.inuse = 0;
+    info->satinfo.inview = 0;
+
+    for(it = 0; it < 12; ++it)
+    {
+        info->satinfo.sat[it].id = it;
+        info->satinfo.sat[it].in_use = in_use = (int)nmea_random(0, 3);
+        info->satinfo.sat[it].elv = (int)nmea_random(0, 90);
+        info->satinfo.sat[it].azimuth = (int)nmea_random(0, 359);
+        info->satinfo.sat[it].sig = (int)(in_use?nmea_random(40, 99):nmea_random(0, 40));
+
+        if(in_use)
+            info->satinfo.inuse++;
+        if(info->satinfo.sat[it].sig > 0)
+            info->satinfo.inview++;
+    }
+
+    return 1;
+}
+
+int nmea_igen_noise_reset(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info __attribute__ ((unused)))
+{
+    return 1;
+}
+
+/*
+ * STATIC generator
+ */
+
+int nmea_igen_static_loop(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info)
+{
+    nmea_time_now(&info->utc);
+    return 1;
+};
+
+int nmea_igen_static_reset(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info)
+{
+    info->satinfo.inuse = 4;
+    info->satinfo.inview = 4;
+
+    info->satinfo.sat[0].id = 1;
+    info->satinfo.sat[0].in_use = 1;
+    info->satinfo.sat[0].elv = 50;
+    info->satinfo.sat[0].azimuth = 0;
+    info->satinfo.sat[0].sig = 99;
+
+    info->satinfo.sat[1].id = 2;
+    info->satinfo.sat[1].in_use = 1;
+    info->satinfo.sat[1].elv = 50;
+    info->satinfo.sat[1].azimuth = 90;
+    info->satinfo.sat[1].sig = 99;
+
+    info->satinfo.sat[2].id = 3;
+    info->satinfo.sat[2].in_use = 1;
+    info->satinfo.sat[2].elv = 50;
+    info->satinfo.sat[2].azimuth = 180;
+    info->satinfo.sat[2].sig = 99;
+
+    info->satinfo.sat[3].id = 4;
+    info->satinfo.sat[3].in_use = 1;
+    info->satinfo.sat[3].elv = 50;
+    info->satinfo.sat[3].azimuth = 270;
+    info->satinfo.sat[3].sig = 99;
+
+    return 1;
+}
+
+int nmea_igen_static_init(nmeaGENERATOR *gen, nmeaINFO *info)
+{
+    info->sig = 3;
+    info->fix = 3;
+
+    nmea_igen_static_reset(gen, info);
+
+    return 1;
+}
+
+/*
+ * SAT_ROTATE generator
+ */
+
+int nmea_igen_rotate_loop(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info)
+{
+    int it;
+    int count = info->satinfo.inview;
+    double deg = 360 / (count?count:1);
+    double srt = (count?(info->satinfo.sat[0].azimuth):0) + 5;
+
+    nmea_time_now(&info->utc);
+
+    for(it = 0; it < count; ++it)
+    {
+        info->satinfo.sat[it].azimuth =
+            (int)((srt >= 360)?srt - 360:srt);
+        srt += deg;
+    }
+
+    return 1;
+};
+
+int nmea_igen_rotate_reset(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info)
+{
+    int it;
+    double deg = 360 / 8;
+    double srt = 0;
+
+    info->satinfo.inuse = 8;
+    info->satinfo.inview = 8;
+
+    for(it = 0; it < info->satinfo.inview; ++it)
+    {
+        info->satinfo.sat[it].id = it + 1;
+        info->satinfo.sat[it].in_use = 1;
+        info->satinfo.sat[it].elv = 5;
+        info->satinfo.sat[it].azimuth = (int)srt;
+        info->satinfo.sat[it].sig = 80;
+        srt += deg;
+    }
+
+    return 1;
+}
+
+int nmea_igen_rotate_init(nmeaGENERATOR *gen, nmeaINFO *info)
+{
+    info->sig = 3;
+    info->fix = 3;
+
+    nmea_igen_rotate_reset(gen, info);
+
+    return 1;
+}
+
+/*
+ * POS_RANDMOVE generator
+ */
+
+int nmea_igen_pos_rmove_init(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info)
+{    
+    info->sig = 3;
+    info->fix = 3;
+    info->direction = info->declination = 0;
+    info->speed = 20;
+    return 1;
+}
+
+int nmea_igen_pos_rmove_loop(nmeaGENERATOR *gen __attribute__ ((unused)),
+		nmeaINFO *info)
+{
+    nmeaPOS crd;
+
+    info->direction += nmea_random(-10, 10);
+    info->speed += nmea_random(-2, 3);
+
+    if(info->direction < 0)
+        info->direction = 359 + info->direction;
+    if(info->direction > 359)
+        info->direction -= 359;
+
+    if(info->speed > 40)
+        info->speed = 40;
+    if(info->speed < 1)
+        info->speed = 1;
+
+    nmea_info2pos(info, &crd);
+    nmea_move_horz(&crd, &crd, info->direction, info->speed / 3600);
+    nmea_pos2info(&crd, info);
+
+    info->declination = info->direction;
+
+    return 1;
+};
+
+int nmea_igen_pos_rmove_destroy(nmeaGENERATOR *gen __attribute__ ((unused)))
+{
+    return 1;
+};
+
+/*
+ * generator create
+ */
+
+nmeaGENERATOR * __nmea_create_generator(int type, nmeaINFO *info)
+{
+    nmeaGENERATOR *gen = 0;
+
+    switch(type)
+    {
+    case NMEA_GEN_NOISE:
+        if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
+            nmea_error("Insufficient memory!");
+        else
+        {
+            memset(gen, 0, sizeof(nmeaGENERATOR));
+            gen->init_call = &nmea_igen_noise_init;
+            gen->loop_call = &nmea_igen_noise_loop;
+            gen->reset_call = &nmea_igen_noise_reset;
+        }
+        break;
+    case NMEA_GEN_STATIC:
+    case NMEA_GEN_SAT_STATIC:
+        if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
+            nmea_error("Insufficient memory!");
+        else
+        {
+            memset(gen, 0, sizeof(nmeaGENERATOR));
+            gen->init_call = &nmea_igen_static_init;
+            gen->loop_call = &nmea_igen_static_loop;
+            gen->reset_call = &nmea_igen_static_reset;
+        }
+        break;
+    case NMEA_GEN_SAT_ROTATE:
+        if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
+            nmea_error("Insufficient memory!");
+        else
+        {
+            memset(gen, 0, sizeof(nmeaGENERATOR));
+            gen->init_call = &nmea_igen_rotate_init;
+            gen->loop_call = &nmea_igen_rotate_loop;
+            gen->reset_call = &nmea_igen_rotate_reset;
+        }
+        break;
+    case NMEA_GEN_POS_RANDMOVE:
+        if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
+            nmea_error("Insufficient memory!");
+        else
+        {
+            memset(gen, 0, sizeof(nmeaGENERATOR));
+            gen->init_call = &nmea_igen_pos_rmove_init;
+            gen->loop_call = &nmea_igen_pos_rmove_loop;
+            gen->destroy_call = &nmea_igen_pos_rmove_destroy;
+        }
+        break;
+    default:
+    /* case NMEA_GEN_ROTATE: */
+        gen = __nmea_create_generator(NMEA_GEN_SAT_ROTATE, info);
+        nmea_gen_add(gen, __nmea_create_generator(NMEA_GEN_POS_RANDMOVE, info));
+        break;
+    };
+
+    return gen;
+}
+
+nmeaGENERATOR * nmea_create_generator(int type, nmeaINFO *info)
+{
+    nmeaGENERATOR *gen = __nmea_create_generator(type, info);
+
+    if(gen)
+        nmea_gen_init(gen, info);
+
+    return gen;
+}
+
+void nmea_destroy_generator(nmeaGENERATOR *gen)
+{
+    nmea_gen_destroy(gen);
+}
diff --git a/lib/pud/nmealib/src/gmath.c b/lib/pud/nmealib/src/gmath.c
new file mode 100644
index 0000000..d0fda8c
--- /dev/null
+++ b/lib/pud/nmealib/src/gmath.c
@@ -0,0 +1,379 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \file gmath.h */
+
+#include <nmea/gmath.h>
+
+#include <math.h>
+
+#include <nmea/config.h>
+
+/**
+ * \brief Convert degree to radian
+ */
+double nmea_degree2radian(double val)
+{ return (val * NMEA_PI180); }
+
+/**
+ * \brief Convert radian to degree
+ */
+double nmea_radian2degree(double val)
+{ return (val / NMEA_PI180); }
+
+/**
+ * \brief Convert NDEG (NMEA degree) to fractional degree
+ */
+double nmea_ndeg2degree(double val)
+{
+    double deg;
+    double fra_part = modf(val / 100.0, &deg);
+    return (deg + ((fra_part * 100.0) / 60.0));
+}
+
+/**
+ * \brief Convert fractional degree to NDEG (NMEA degree)
+ */
+double nmea_degree2ndeg(double val)
+{
+    double deg;
+    double fra_part = modf(val, &deg);
+    return ((deg * 100.0) + (fra_part * 60.0));
+}
+
+/**
+ * \brief Convert NDEG (NMEA degree) to radian
+ */
+double nmea_ndeg2radian(double val)
+{ return nmea_degree2radian(nmea_ndeg2degree(val)); }
+
+/**
+ * \brief Convert radian to NDEG (NMEA degree)
+ */
+double nmea_radian2ndeg(double val)
+{ return nmea_degree2ndeg(nmea_radian2degree(val)); }
+
+/**
+ * \brief Calculate PDOP (Position Dilution Of Precision) factor
+ */
+double nmea_calc_pdop(double hdop, double vdop)
+{
+    return sqrt(pow(hdop, 2) + pow(vdop, 2));
+}
+
+double nmea_dop2meters(double dop)
+{ return (dop * NMEA_DOP_FACTOR); }
+
+double nmea_meters2dop(double meters)
+{ return (meters / NMEA_DOP_FACTOR); }
+
+/**
+ * \brief Calculate distance between two points
+ * \return Distance in meters
+ */
+double nmea_distance(
+        const nmeaPOS *from_pos,    /**< From position in radians */
+        const nmeaPOS *to_pos       /**< To position in radians */
+        )
+{
+    double dist = ((double)NMEA_EARTHRADIUS_M) * acos(
+        sin(to_pos->lat) * sin(from_pos->lat) +
+        cos(to_pos->lat) * cos(from_pos->lat) * cos(to_pos->lon - from_pos->lon)
+        );
+    return dist;
+}
+
+/**
+ * \brief Calculate distance between two points
+ * This function uses an algorithm for an oblate spheroid earth model.
+ * The algorithm is described here: 
+ * http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
+ * \return Distance in meters
+ */
+double nmea_distance_ellipsoid(
+        const nmeaPOS *from_pos,    /**< From position in radians */
+        const nmeaPOS *to_pos,      /**< To position in radians */
+        double *from_azimuth,       /**< (O) azimuth at "from" position in radians */
+        double *to_azimuth          /**< (O) azimuth at "to" position in radians */
+        )
+{
+    /* All variables */
+    double f, a, b, sqr_a, sqr_b;
+    double L, phi1, phi2, U1, U2, sin_U1, sin_U2, cos_U1, cos_U2;
+    double sigma, sin_sigma, cos_sigma, cos_2_sigmam, sqr_cos_2_sigmam, sqr_cos_alpha, lambda, sin_lambda, cos_lambda, delta_lambda;
+    int remaining_steps; 
+    double sqr_u, A, B, delta_sigma;
+
+    /* Check input */
+    NMEA_ASSERT(from_pos != 0);
+    NMEA_ASSERT(to_pos != 0);
+
+    if ((from_pos->lat == to_pos->lat) && (from_pos->lon == to_pos->lon))
+    { /* Identical points */
+        if ( from_azimuth != 0 )
+            *from_azimuth = 0;
+        if ( to_azimuth != 0 )
+            *to_azimuth = 0;
+        return 0;    
+    } /* Identical points */
+
+    /* Earth geometry */
+    f = NMEA_EARTH_FLATTENING;
+    a = NMEA_EARTH_SEMIMAJORAXIS_M;
+    b = (1 - f) * a;
+    sqr_a = a * a;
+    sqr_b = b * b;
+
+    /* Calculation */
+    L = to_pos->lon - from_pos->lon;
+    phi1 = from_pos->lat;
+    phi2 = to_pos->lat;
+    U1 = atan((1 - f) * tan(phi1));
+    U2 = atan((1 - f) * tan(phi2));
+    sin_U1 = sin(U1);
+    sin_U2 = sin(U2);
+    cos_U1 = cos(U1);
+    cos_U2 = cos(U2);
+
+    /* Initialize iteration */
+    sigma = 0;
+    sin_sigma = sin(sigma);
+    cos_sigma = cos(sigma);
+    cos_2_sigmam = 0;
+    sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam;
+    sqr_cos_alpha = 0;
+    lambda = L;
+    sin_lambda = sin(lambda);                            
+    cos_lambda = cos(lambda);                       
+    delta_lambda = lambda;
+    remaining_steps = 20; 
+
+    while ((delta_lambda > 1e-12) && (remaining_steps > 0)) 
+    { /* Iterate */
+        /* Variables */
+        double tmp1, tmp2, sin_alpha, cos_alpha, C, lambda_prev;
+
+        /* Calculation */
+        tmp1 = cos_U2 * sin_lambda;
+        tmp2 = cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda;  
+        sin_sigma = sqrt(tmp1 * tmp1 + tmp2 * tmp2);                
+        cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda;   
+        sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma;  
+        cos_alpha = cos(asin(sin_alpha));                 
+        sqr_cos_alpha = cos_alpha * cos_alpha;                     
+        cos_2_sigmam = cos_sigma - 2 * sin_U1 * sin_U2 / sqr_cos_alpha;
+        sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam; 
+        C = f / 16 * sqr_cos_alpha * (4 + f * (4 - 3 * sqr_cos_alpha));
+        lambda_prev = lambda; 
+        sigma = asin(sin_sigma); 
+        lambda = L + 
+            (1 - C) * f * sin_alpha
+            * (sigma + C * sin_sigma * (cos_2_sigmam + C * cos_sigma * (-1 + 2 * sqr_cos_2_sigmam)));                                                
+        delta_lambda = lambda_prev - lambda; 
+        if ( delta_lambda < 0 ) delta_lambda = -delta_lambda; 
+        sin_lambda = sin(lambda);
+        cos_lambda = cos(lambda);
+        remaining_steps--; 
+    }  /* Iterate */
+
+    /* More calculation  */
+    sqr_u = sqr_cos_alpha * (sqr_a - sqr_b) / sqr_b; 
+    A = 1 + sqr_u / 16384 * (4096 + sqr_u * (-768 + sqr_u * (320 - 175 * sqr_u)));
+    B = sqr_u / 1024 * (256 + sqr_u * (-128 + sqr_u * (74 - 47 * sqr_u)));
+    delta_sigma = B * sin_sigma * ( 
+        cos_2_sigmam + B / 4 * ( 
+        cos_sigma * (-1 + 2 * sqr_cos_2_sigmam) -
+        B / 6 * cos_2_sigmam * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * sqr_cos_2_sigmam)
+        ));
+
+    /* Calculate result */
+    if ( from_azimuth != 0 )
+    {
+        double tan_alpha_1 = cos_U2 * sin_lambda / (cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda);
+        *from_azimuth = atan(tan_alpha_1);
+    }
+    if ( to_azimuth != 0 )
+    {
+        double tan_alpha_2 = cos_U1 * sin_lambda / (-sin_U1 * cos_U2 + cos_U1 * sin_U2 * cos_lambda);
+        *to_azimuth = atan(tan_alpha_2);
+    }
+
+    return b * A * (sigma - delta_sigma);
+}
+
+/**
+ * \brief Horizontal move of point position
+ */
+int nmea_move_horz(
+    const nmeaPOS *start_pos,   /**< Start position in radians */
+    nmeaPOS *end_pos,           /**< Result position in radians */
+    double azimuth,             /**< Azimuth (degree) [0, 359] */
+    double distance             /**< Distance (km) */
+    )
+{
+    nmeaPOS p1 = *start_pos;
+    int RetVal = 1;
+
+    distance /= NMEA_EARTHRADIUS_KM; /* Angular distance covered on earth's surface */
+    azimuth = nmea_degree2radian(azimuth);
+
+    end_pos->lat = asin(
+        sin(p1.lat) * cos(distance) + cos(p1.lat) * sin(distance) * cos(azimuth));
+    end_pos->lon = p1.lon + atan2(
+        sin(azimuth) * sin(distance) * cos(p1.lat), cos(distance) - sin(p1.lat) * sin(end_pos->lat));
+
+    if(NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon))
+    {
+        end_pos->lat = 0; end_pos->lon = 0;
+        RetVal = 0;
+    }
+
+    return RetVal;
+}
+
+/**
+ * \brief Horizontal move of point position
+ * This function uses an algorithm for an oblate spheroid earth model.
+ * The algorithm is described here: 
+ * http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
+ */
+int nmea_move_horz_ellipsoid(
+    const nmeaPOS *start_pos,   /**< Start position in radians */
+    nmeaPOS *end_pos,           /**< (O) Result position in radians */
+    double azimuth,             /**< Azimuth in radians */
+    double distance,            /**< Distance (km) */
+    double *end_azimuth         /**< (O) Azimuth at end position in radians */
+    )
+{
+    /* Variables */
+    double f, a, b, sqr_a, sqr_b;
+    double phi1, tan_U1, sin_U1, cos_U1, s, alpha1, sin_alpha1, cos_alpha1;
+    double sigma1, sin_alpha, sqr_cos_alpha, sqr_u, A, B;
+    double sigma_initial, sigma, sigma_prev, sin_sigma, cos_sigma, cos_2_sigmam, sqr_cos_2_sigmam, delta_sigma;
+    int remaining_steps;
+    double tmp1, phi2, lambda, C, L;
+    
+    /* Check input */
+    NMEA_ASSERT(start_pos != 0);
+    NMEA_ASSERT(end_pos != 0);
+    
+    if (fabs(distance) < 1e-12)
+    { /* No move */
+        *end_pos = *start_pos;
+        if ( end_azimuth != 0 ) *end_azimuth = azimuth;
+        return ! (NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon));
+    } /* No move */
+
+    /* Earth geometry */
+    f = NMEA_EARTH_FLATTENING;
+    a = NMEA_EARTH_SEMIMAJORAXIS_M;
+    b = (1 - f) * a;
+    sqr_a = a * a;
+    sqr_b = b * b;
+    
+    /* Calculation */
+    phi1 = start_pos->lat;
+    tan_U1 = (1 - f) * tan(phi1);
+    cos_U1 = 1 / sqrt(1 + tan_U1 * tan_U1);
+    sin_U1 = tan_U1 * cos_U1;
+    s = distance;
+    alpha1 = azimuth;
+    sin_alpha1 = sin(alpha1);
+    cos_alpha1 = cos(alpha1);
+    sigma1 = atan2(tan_U1, cos_alpha1);
+    sin_alpha = cos_U1 * sin_alpha1;
+    sqr_cos_alpha = 1 - sin_alpha * sin_alpha;
+    sqr_u = sqr_cos_alpha * (sqr_a - sqr_b) / sqr_b; 
+    A = 1 + sqr_u / 16384 * (4096 + sqr_u * (-768 + sqr_u * (320 - 175 * sqr_u)));
+    B = sqr_u / 1024 * (256 + sqr_u * (-128 + sqr_u * (74 - 47 * sqr_u)));
+    
+    /* Initialize iteration */
+    sigma_initial = s / (b * A);
+    sigma = sigma_initial;
+    sin_sigma = sin(sigma);
+    cos_sigma = cos(sigma);
+    cos_2_sigmam = cos(2 * sigma1 + sigma);
+    sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam;
+    delta_sigma = 0;
+    sigma_prev = 2 * NMEA_PI;
+    remaining_steps = 20;
+
+    while ((fabs(sigma - sigma_prev) > 1e-12) && (remaining_steps > 0))
+    { /* Iterate */
+        cos_2_sigmam = cos(2 * sigma1 + sigma);
+        sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam;
+        sin_sigma = sin(sigma);
+        cos_sigma = cos(sigma);
+        delta_sigma = B * sin_sigma * ( 
+             cos_2_sigmam + B / 4 * ( 
+             cos_sigma * (-1 + 2 * sqr_cos_2_sigmam) - 
+             B / 6 * cos_2_sigmam * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * sqr_cos_2_sigmam)
+             ));
+        sigma_prev = sigma;
+        sigma = sigma_initial + delta_sigma;
+        remaining_steps --;
+    } /* Iterate */
+    
+    /* Calculate result */
+    tmp1 = (sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_alpha1);
+    phi2 = atan2(
+            sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_alpha1,
+            (1 - f) * sqrt(sin_alpha * sin_alpha + tmp1 * tmp1)
+            );
+    lambda = atan2(
+            sin_sigma * sin_alpha1,
+            cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_alpha1
+            );
+    C = f / 16 * sqr_cos_alpha * (4 + f * (4 - 3 * sqr_cos_alpha));
+    L = lambda -
+        (1 - C) * f * sin_alpha * (
+        sigma + C * sin_sigma *
+        (cos_2_sigmam + C * cos_sigma * (-1 + 2 * sqr_cos_2_sigmam))
+        );
+    
+    /* Result */
+    end_pos->lon = start_pos->lon + L;
+    end_pos->lat = phi2;
+    if ( end_azimuth != 0 )
+    {
+        *end_azimuth = atan2(
+            sin_alpha, -sin_U1 * sin_sigma + cos_U1 * cos_sigma * cos_alpha1
+            );
+    }
+    return ! (NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon));
+}
+
+/**
+ * \brief Convert position from INFO to radians position
+ */
+void nmea_info2pos(const nmeaINFO *info, nmeaPOS *pos)
+{
+    pos->lat = nmea_ndeg2radian(info->lat);
+    pos->lon = nmea_ndeg2radian(info->lon);
+}
+
+/**
+ * \brief Convert radians position to INFOs position
+ */
+void nmea_pos2info(const nmeaPOS *pos, nmeaINFO *info)
+{
+    info->lat = nmea_radian2ndeg(pos->lat);
+    info->lon = nmea_radian2ndeg(pos->lon);
+}
diff --git a/lib/pud/nmealib/src/info.c b/lib/pud/nmealib/src/info.c
new file mode 100644
index 0000000..7cd20d4
--- /dev/null
+++ b/lib/pud/nmealib/src/info.c
@@ -0,0 +1,347 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/info.h>
+
+#include <nmea/sentence.h>
+#include <nmea/gmath.h>
+#include <nmea/time.h>
+
+#include <string.h>
+#include <math.h>
+
+void nmea_zero_INFO(nmeaINFO *info)
+{
+	if (!info) {
+		return;
+	}
+
+    memset(info, 0, sizeof(nmeaINFO));
+    nmea_time_now(&info->utc);
+    info->sig = NMEA_SIG_BAD;
+    info->fix = NMEA_FIX_BAD;
+}
+
+/**
+ * Determine whether a given nmeaINFO structure has a certain field.
+ *
+ * nmeaINFO dependencies:
+ <pre>
+ field/sentence GPGGA   GPGSA   GPGSV   GPRMC   GPVTG
+ smask:         x       x       x       x       x
+ utc:           x                       x
+ sig:           x                       x
+ fix:                   x               x
+ PDOP:                  x
+ HDOP:          x       x
+ VDOP:                  x
+ lat:           x                       x
+ lon:           x                       x
+ elv:           x
+ speed:                                 x       x
+ direction:                             x       x
+ declination:                                   x
+ satinfo:               x       x
+ </pre>
+ *
+ * @param smask
+ * the smask of a nmeaINFO structure
+ * @param fieldName
+ * the field name
+ *
+ * @return
+ * - true when the nmeaINFO structure has the field
+ * - false otherwise
+ */
+bool nmea_INFO_has_field(int smask, nmeaINFO_FIELD fieldName) {
+	switch (fieldName) {
+		case SMASK:
+			return true;
+
+		case UTC:
+		case SIG:
+		case LAT:
+		case LON:
+			return ((smask & (GPGGA | GPRMC)) != 0);
+
+		case FIX:
+			return ((smask & (GPGSA | GPRMC)) != 0);
+
+		case PDOP:
+		case VDOP:
+			return ((smask & GPGSA) != 0);
+
+		case HDOP:
+			return ((smask & (GPGGA | GPGSA)) != 0);
+
+		case ELV:
+			return ((smask & GPGGA) != 0);
+
+		case SPEED:
+		case DIRECTION:
+			return ((smask & (GPRMC | GPVTG)) != 0);
+
+		case DECLINATION:
+			return ((smask & GPVTG) != 0);
+
+		case SATINFO:
+			return ((smask & (GPGSA | GPGSV)) != 0);
+
+		default:
+			return false;
+	}
+}
+
+/**
+ * Sanitise the NMEA info, make sure that:
+ * - latitude is in the range [-9000, 9000],
+ * - longitude is in the range [-18000, 18000],
+ * - DOPs are positive,
+ * - speed is positive,
+ * - direction is in the range [0, 360>.
+ *
+ * Time is set to the current time when not present.
+ *
+ * When a field is not present then it is reset to its default (NMEA_SIG_BAD,
+ * NMEA_FIX_BAD, 0).
+ *
+ * Satinfo is not touched.
+ *
+ * @param nmeaInfo
+ * the NMEA info structure to sanitise
+ */
+void nmea_INFO_sanitise(nmeaINFO *nmeaInfo) {
+	double lat = 0;
+	double lon = 0;
+	double speed = 0;
+	double direction = 0;
+	bool latAdjusted = false;
+	bool lonAdjusted = false;
+	bool speedAdjusted = false;
+	bool directionAdjusted = false;
+
+	if (!nmeaInfo) {
+		return;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, UTC)) {
+		nmea_time_now(&nmeaInfo->utc);
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, SIG)) {
+		nmeaInfo->sig = NMEA_SIG_BAD;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, FIX)) {
+		nmeaInfo->fix = NMEA_FIX_BAD;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, PDOP)) {
+		nmeaInfo->PDOP = 0;
+	} else {
+		nmeaInfo->PDOP = fabs(nmeaInfo->PDOP);
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, HDOP)) {
+		nmeaInfo->HDOP = 0;
+	} else {
+		nmeaInfo->HDOP = fabs(nmeaInfo->HDOP);
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, VDOP)) {
+		nmeaInfo->VDOP = 0;
+	} else {
+		nmeaInfo->VDOP = fabs(nmeaInfo->VDOP);
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, LAT)) {
+		nmeaInfo->lat = 0;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, LON)) {
+		nmeaInfo->lon = 0;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, ELV)) {
+		nmeaInfo->elv = 0;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, SPEED)) {
+		nmeaInfo->speed = 0;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, DIRECTION)) {
+		nmeaInfo->direction = 0;
+	}
+
+	if (!nmea_INFO_has_field(nmeaInfo->smask, DECLINATION)) {
+		nmeaInfo->declination = 0;
+	}
+
+	/* satinfo is not used */
+
+	/*
+	 * lat
+	 */
+
+	lat = nmeaInfo->lat;
+	lon = nmeaInfo->lon;
+
+	/* force lat in [-18000, 18000] */
+	while (lat < -18000.0) {
+		lat += 36000.0;
+		latAdjusted = true;
+	}
+	while (lat > 18000.0) {
+		lat -= 36000.0;
+		latAdjusted = true;
+	}
+
+	/* lat is now in [-18000, 18000] */
+
+	/* force lat from <9000, 18000] in [9000, 0] */
+	if (lat > 9000.0) {
+		lat = 18000.0 - lat;
+		lon += 18000.0;
+		latAdjusted = true;
+		lonAdjusted = true;
+	}
+
+	/* force lat from [-18000, -9000> in [0, -9000] */
+	if (lat < -9000.0) {
+		lat = -18000.0 - lat;
+		lon += 18000.0;
+		latAdjusted = true;
+		lonAdjusted = true;
+	}
+
+	/* lat is now in [-9000, 9000] */
+
+	if (latAdjusted) {
+		nmeaInfo->lat = lat;
+	}
+
+	/*
+	 * lon
+	 */
+
+	/* force lon in [-18000, 18000] */
+	while (lon < -18000.0) {
+		lon += 36000.0;
+		lonAdjusted = true;
+	}
+	while (lon > 18000.0) {
+		lon -= 36000.0;
+		lonAdjusted = true;
+	}
+
+	/* lon is now in [-18000, 18000] */
+
+	if (lonAdjusted) {
+		nmeaInfo->lon = lon;
+	}
+
+	/*
+	 * speed
+	 */
+
+	speed = nmeaInfo->speed;
+	direction = nmeaInfo->direction;
+
+	if (speed < 0.0) {
+		speed = -speed;
+		direction += 180.0;
+		speedAdjusted = true;
+		directionAdjusted = true;
+	}
+
+	/* speed is now in [0, max> */
+
+	if (speedAdjusted) {
+		nmeaInfo->speed = speed;
+	}
+
+	/*
+	 * direction
+	 */
+
+	/* force direction in [0, 360> */
+	while (direction < 0.0) {
+		direction += 360.0;
+		directionAdjusted = true;
+	}
+	while (direction >= 360.0) {
+		direction -= 360.0;
+		directionAdjusted = true;
+	}
+
+	/* direction is now in [0, 360> */
+
+	if (directionAdjusted) {
+		nmeaInfo->direction = direction;
+	}
+}
+
+/**
+ * Converts the position fields to degrees and DOP fields to meters so that
+ * all fields use normal metric units.
+ *
+ * @param nmeaInfo
+ * the nmeaINFO
+ */
+void nmea_INFO_unit_conversion(nmeaINFO * nmeaInfo) {
+	if (!nmeaInfo) {
+		return;
+	}
+
+	/* smask (already in correct format) */
+
+	/* utc (already in correct format) */
+
+	/* sig (already in correct format) */
+	/* fix (already in correct format) */
+
+	if (nmea_INFO_has_field(nmeaInfo->smask, PDOP)) {
+		nmeaInfo->PDOP = nmea_dop2meters(nmeaInfo->PDOP);
+	}
+
+	if (nmea_INFO_has_field(nmeaInfo->smask, HDOP)) {
+		nmeaInfo->HDOP = nmea_dop2meters(nmeaInfo->HDOP);
+	}
+
+	if (nmea_INFO_has_field(nmeaInfo->smask, VDOP)) {
+		nmeaInfo->VDOP = nmea_dop2meters(nmeaInfo->VDOP);
+	}
+
+	if (nmea_INFO_has_field(nmeaInfo->smask, LAT)) {
+		nmeaInfo->lat = nmea_ndeg2degree(nmeaInfo->lat);
+	}
+
+	if (nmea_INFO_has_field(nmeaInfo->smask, LON)) {
+		nmeaInfo->lon = nmea_ndeg2degree(nmeaInfo->lon);
+	}
+
+	/* elv (already in correct format) */
+	/* speed (already in correct format) */
+	/* direction (already in correct format) */
+	/* declination (already in correct format) */
+
+	/* satinfo (not used) */
+}
diff --git a/lib/pud/nmealib/src/parse.c b/lib/pud/nmealib/src/parse.c
new file mode 100644
index 0000000..1d54840
--- /dev/null
+++ b/lib/pud/nmealib/src/parse.c
@@ -0,0 +1,513 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file parse.h
+ * \brief Functions of a low level for analysis of
+ * packages of NMEA stream.
+ *
+ * \code
+ * ...
+ * ptype = nmea_pack_type(
+ *     (const char *)parser->buffer + nparsed + 1,
+ *     parser->buff_use - nparsed - 1);
+ * 
+ * if(0 == (node = malloc(sizeof(nmeaParserNODE))))
+ *     goto mem_fail;
+ * 
+ * node->pack = 0;
+ * 
+ * switch(ptype)
+ * {
+ * case GPGGA:
+ *     if(0 == (node->pack = malloc(sizeof(nmeaGPGGA))))
+ *         goto mem_fail;
+ *     node->packType = GPGGA;
+ *     if(!nmea_parse_GPGGA(
+ *         (const char *)parser->buffer + nparsed,
+ *         sen_sz, (nmeaGPGGA *)node->pack))
+ *     {
+ *         free(node);
+ *         node = 0;
+ *     }
+ *     break;
+ * case GPGSA:
+ *     if(0 == (node->pack = malloc(sizeof(nmeaGPGSA))))
+ *         goto mem_fail;
+ *     node->packType = GPGSA;
+ *     if(!nmea_parse_GPGSA(
+ *         (const char *)parser->buffer + nparsed,
+ *         sen_sz, (nmeaGPGSA *)node->pack))
+ *     {
+ *         free(node);
+ *         node = 0;
+ *     }
+ *     break;
+ * ...
+ * \endcode
+ */
+
+#include <nmea/parse.h>
+
+#include <string.h>
+
+#include <nmea/config.h>
+#include <nmea/context.h>
+#include <nmea/tok.h>
+#include <nmea/units.h>
+
+#define NMEA_TIMEPARSE_BUF  (256)
+
+int _nmea_parse_time(const char *buff, int buff_sz, nmeaTIME *res)
+{
+    int success = 0;
+
+    switch(buff_sz)
+    {
+    case sizeof("hhmmss") - 1:
+        success = (3 == nmea_scanf(buff, buff_sz,
+            "%2d%2d%2d", &(res->hour), &(res->min), &(res->sec)
+            ));
+        break;
+    case sizeof("hhmmss.s") - 1:
+    case sizeof("hhmmss.ss") - 1:
+    case sizeof("hhmmss.sss") - 1:
+        success = (4 == nmea_scanf(buff, buff_sz,
+            "%2d%2d%2d.%d", &(res->hour), &(res->min), &(res->sec), &(res->hsec)
+            ));
+        break;
+    default:
+        nmea_error("Parse of time error (format error)!");
+        success = 0;
+        break;
+    }
+
+    return (success?0:-1);        
+}
+
+/**
+ * \brief Define packet type by header (nmeaPACKTYPE).
+ * @param buff a constant character pointer of packet buffer.
+ * @param buff_sz buffer size.
+ * @return The defined packet type
+ * @see nmeaPACKTYPE
+ */
+int nmea_pack_type(const char *buff, int buff_sz)
+{
+    static const char *pheads[] = {
+        "GPGGA",
+        "GPGSA",
+        "GPGSV",
+        "GPRMC",
+        "GPVTG",
+    };
+
+    NMEA_ASSERT(buff);
+
+    if(buff_sz < 5)
+        return GPNON;
+    else if(0 == memcmp(buff, pheads[0], 5))
+        return GPGGA;
+    else if(0 == memcmp(buff, pheads[1], 5))
+        return GPGSA;
+    else if(0 == memcmp(buff, pheads[2], 5))
+        return GPGSV;
+    else if(0 == memcmp(buff, pheads[3], 5))
+        return GPRMC;
+    else if(0 == memcmp(buff, pheads[4], 5))
+        return GPVTG;
+
+    return GPNON;
+}
+
+/**
+ * \brief Find tail of packet ("\r\n") in buffer and check control sum (CRC).
+ * @param buff a constant character pointer of packets buffer.
+ * @param buff_sz buffer size.
+ * @param res_crc a integer pointer for return CRC of packet (must be defined).
+ * @return Number of bytes to packet tail.
+ */
+int nmea_find_tail(const char *buff, int buff_sz, int *res_crc)
+{
+    static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */;
+
+    const char *end_buff = buff + buff_sz;
+    int nread = 0;
+    int crc = 0;
+
+    NMEA_ASSERT(buff && res_crc);
+
+    *res_crc = -1;
+
+    for(;buff < end_buff; ++buff, ++nread)
+    {
+        if(('$' == *buff) && nread)
+        {
+            buff = 0;
+            break;
+        }
+        else if('*' == *buff)
+        {
+            if(buff + tail_sz <= end_buff && '\r' == buff[3] && '\n' == buff[4])
+            {
+                *res_crc = nmea_atoi(buff + 1, 2, 16);
+                nread = buff_sz - (int)(end_buff - (buff + tail_sz));
+                if(*res_crc != crc)
+                {
+                    *res_crc = -1;
+                    buff = 0;
+                }
+            }
+
+            break;
+        }
+        else if(nread)
+            crc ^= (int)*buff;
+    }
+
+    if(*res_crc < 0 && buff)
+        nread = 0;
+
+    return nread;
+}
+
+/**
+ * \brief Parse GGA packet from buffer.
+ * @param buff a constant character pointer of packet buffer.
+ * @param buff_sz buffer size.
+ * @param pack a pointer of packet which will filled by function.
+ * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
+ */
+int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack)
+{
+    char time_buff[NMEA_TIMEPARSE_BUF];
+
+    NMEA_ASSERT(buff && pack);
+
+    memset(pack, 0, sizeof(nmeaGPGGA));
+
+    nmea_trace_buff(buff, buff_sz);
+
+    if(14 != nmea_scanf(buff, buff_sz,
+        "$GPGGA,%s,%f,%C,%f,%C,%d,%d,%f,%f,%C,%f,%C,%f,%d*",
+        &(time_buff[0]),
+        &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew),
+        &(pack->sig), &(pack->satinuse), &(pack->HDOP), &(pack->elv), &(pack->elv_units),
+        &(pack->diff), &(pack->diff_units), &(pack->dgps_age), &(pack->dgps_sid)))
+    {
+        nmea_error("GPGGA parse error!");
+        return 0;
+    }
+
+    if(0 != _nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc)))
+    {
+        nmea_error("GPGGA time parse error!");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * \brief Parse GSA packet from buffer.
+ * @param buff a constant character pointer of packet buffer.
+ * @param buff_sz buffer size.
+ * @param pack a pointer of packet which will filled by function.
+ * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
+ */
+int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack)
+{
+    NMEA_ASSERT(buff && pack);
+
+    memset(pack, 0, sizeof(nmeaGPGSA));
+
+    nmea_trace_buff(buff, buff_sz);
+
+    if(17 != nmea_scanf(buff, buff_sz,
+        "$GPGSA,%C,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f*",
+        &(pack->fix_mode), &(pack->fix_type),
+        &(pack->sat_prn[0]), &(pack->sat_prn[1]), &(pack->sat_prn[2]), &(pack->sat_prn[3]), &(pack->sat_prn[4]), &(pack->sat_prn[5]),
+        &(pack->sat_prn[6]), &(pack->sat_prn[7]), &(pack->sat_prn[8]), &(pack->sat_prn[9]), &(pack->sat_prn[10]), &(pack->sat_prn[11]),
+        &(pack->PDOP), &(pack->HDOP), &(pack->VDOP)))
+    {
+        nmea_error("GPGSA parse error!");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * \brief Parse GSV packet from buffer.
+ * @param buff a constant character pointer of packet buffer.
+ * @param buff_sz buffer size.
+ * @param pack a pointer of packet which will filled by function.
+ * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
+ */
+int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack)
+{
+    int nsen, nsat;
+
+    NMEA_ASSERT(buff && pack);
+
+    memset(pack, 0, sizeof(nmeaGPGSV));
+
+    nmea_trace_buff(buff, buff_sz);
+
+    nsen = nmea_scanf(buff, buff_sz,
+        "$GPGSV,%d,%d,%d,"
+        "%d,%d,%d,%d,"
+        "%d,%d,%d,%d,"
+        "%d,%d,%d,%d,"
+        "%d,%d,%d,%d*",
+        &(pack->pack_count), &(pack->pack_index), &(pack->sat_count),
+        &(pack->sat_data[0].id), &(pack->sat_data[0].elv), &(pack->sat_data[0].azimuth), &(pack->sat_data[0].sig),
+        &(pack->sat_data[1].id), &(pack->sat_data[1].elv), &(pack->sat_data[1].azimuth), &(pack->sat_data[1].sig),
+        &(pack->sat_data[2].id), &(pack->sat_data[2].elv), &(pack->sat_data[2].azimuth), &(pack->sat_data[2].sig),
+        &(pack->sat_data[3].id), &(pack->sat_data[3].elv), &(pack->sat_data[3].azimuth), &(pack->sat_data[3].sig));
+
+    nsat = (pack->pack_index - 1) * NMEA_SATINPACK;
+    nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK;
+    nsat = nsat * 4 + 3 /* first three sentence`s */;
+
+    if(nsen < nsat || nsen > (NMEA_SATINPACK * 4 + 3))
+    {
+        nmea_error("GPGSV parse error!");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * \brief Parse RMC packet from buffer.
+ * @param buff a constant character pointer of packet buffer.
+ * @param buff_sz buffer size.
+ * @param pack a pointer of packet which will filled by function.
+ * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
+ */
+int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack)
+{
+    int nsen;
+    char time_buff[NMEA_TIMEPARSE_BUF];
+
+    NMEA_ASSERT(buff && pack);
+
+    memset(pack, 0, sizeof(nmeaGPRMC));
+
+    nmea_trace_buff(buff, buff_sz);
+
+    nsen = nmea_scanf(buff, buff_sz,
+        "$GPRMC,%s,%C,%f,%C,%f,%C,%f,%f,%2d%2d%2d,%f,%C,%C*",
+        &(time_buff[0]),
+        &(pack->status), &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew),
+        &(pack->speed), &(pack->direction),
+        &(pack->utc.day), &(pack->utc.mon), &(pack->utc.year),
+        &(pack->declination), &(pack->declin_ew), &(pack->mode));
+
+    if(nsen != 13 && nsen != 14)
+    {
+        nmea_error("GPRMC parse error!");
+        return 0;
+    }
+
+    if(0 != _nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc)))
+    {
+        nmea_error("GPRMC time parse error!");
+        return 0;
+    }
+
+    if(pack->utc.year < 90)
+        pack->utc.year += 100;
+    pack->utc.mon -= 1;
+
+    return 1;
+}
+
+/**
+ * \brief Parse VTG packet from buffer.
+ * @param buff a constant character pointer of packet buffer.
+ * @param buff_sz buffer size.
+ * @param pack a pointer of packet which will filled by function.
+ * @return 1 (true) - if parsed successfully or 0 (false) - if fail.
+ */
+int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack)
+{
+    NMEA_ASSERT(buff && pack);
+
+    memset(pack, 0, sizeof(nmeaGPVTG));
+
+    nmea_trace_buff(buff, buff_sz);
+
+    if(8 != nmea_scanf(buff, buff_sz,
+        "$GPVTG,%f,%C,%f,%C,%f,%C,%f,%C*",
+        &(pack->dir), &(pack->dir_t),
+        &(pack->dec), &(pack->dec_m),
+        &(pack->spn), &(pack->spn_n),
+        &(pack->spk), &(pack->spk_k)))
+    {
+        nmea_error("GPVTG parse error!");
+        return 0;
+    }
+
+    if( pack->dir_t != 'T' ||
+        pack->dec_m != 'M' ||
+        pack->spn_n != 'N' ||
+        pack->spk_k != 'K')
+    {
+        nmea_error("GPVTG parse error (format error)!");
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * \brief Fill nmeaINFO structure by GGA packet data.
+ * @param pack a pointer of packet structure.
+ * @param info a pointer of summary information structure.
+ */
+void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info)
+{
+    NMEA_ASSERT(pack && info);
+
+    info->utc.hour = pack->utc.hour;
+    info->utc.min = pack->utc.min;
+    info->utc.sec = pack->utc.sec;
+    info->utc.hsec = pack->utc.hsec;
+    info->sig = pack->sig;
+    info->HDOP = pack->HDOP;
+    info->elv = pack->elv;
+    info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat));
+    info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon));
+    info->smask |= GPGGA;
+}
+
+/**
+ * \brief Fill nmeaINFO structure by GSA packet data.
+ * @param pack a pointer of packet structure.
+ * @param info a pointer of summary information structure.
+ */
+void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info)
+{
+    int i, j, nuse = 0;
+
+    NMEA_ASSERT(pack && info);
+
+    info->fix = pack->fix_type;
+    info->PDOP = pack->PDOP;
+    info->HDOP = pack->HDOP;
+    info->VDOP = pack->VDOP;
+
+    for(i = 0; i < NMEA_MAXSAT; ++i)
+    {
+        for(j = 0; j < info->satinfo.inview; ++j)
+        {
+            if(pack->sat_prn[i] && pack->sat_prn[i] == info->satinfo.sat[j].id)
+            {
+                info->satinfo.sat[j].in_use = 1;
+                nuse++;
+            }
+        }
+    }
+
+    info->satinfo.inuse = nuse;
+    info->smask |= GPGSA;
+}
+
+/**
+ * \brief Fill nmeaINFO structure by GSV packet data.
+ * @param pack a pointer of packet structure.
+ * @param info a pointer of summary information structure.
+ */
+void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info)
+{
+    int isat, isi, nsat;
+
+    NMEA_ASSERT(pack && info);
+
+    if(pack->pack_index > pack->pack_count ||
+        pack->pack_index * NMEA_SATINPACK > NMEA_MAXSAT)
+        return;
+
+    if(pack->pack_index < 1)
+        pack->pack_index = 1;
+
+    info->satinfo.inview = pack->sat_count;
+
+    nsat = (pack->pack_index - 1) * NMEA_SATINPACK;
+    nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK;
+
+    for(isat = 0; isat < nsat; ++isat)
+    {
+        isi = (pack->pack_index - 1) * NMEA_SATINPACK + isat;
+        info->satinfo.sat[isi].id = pack->sat_data[isat].id;
+        info->satinfo.sat[isi].elv = pack->sat_data[isat].elv;
+        info->satinfo.sat[isi].azimuth = pack->sat_data[isat].azimuth;
+        info->satinfo.sat[isi].sig = pack->sat_data[isat].sig;
+    }
+
+    info->smask |= GPGSV;
+}
+
+/**
+ * \brief Fill nmeaINFO structure by RMC packet data.
+ * @param pack a pointer of packet structure.
+ * @param info a pointer of summary information structure.
+ */
+void nmea_GPRMC2info(nmeaGPRMC *pack, nmeaINFO *info)
+{
+    NMEA_ASSERT(pack && info);
+
+    if('A' == pack->status)
+    {
+        if(NMEA_SIG_BAD == info->sig)
+            info->sig = NMEA_SIG_MID;
+        if(NMEA_FIX_BAD == info->fix)
+            info->fix = NMEA_FIX_2D;
+    }
+    else if('V' == pack->status)
+    {
+        info->sig = NMEA_SIG_BAD;
+        info->fix = NMEA_FIX_BAD;
+    }
+
+    info->utc = pack->utc;
+    info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat));
+    info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon));
+    info->speed = pack->speed * NMEA_TUD_KNOTS;
+    info->direction = pack->direction;
+    info->smask |= GPRMC;
+}
+
+/**
+ * \brief Fill nmeaINFO structure by VTG packet data.
+ * @param pack a pointer of packet structure.
+ * @param info a pointer of summary information structure.
+ */
+void nmea_GPVTG2info(nmeaGPVTG *pack, nmeaINFO *info)
+{
+    NMEA_ASSERT(pack && info);
+
+    info->direction = pack->dir;
+    info->declination = pack->dec;
+    info->speed = pack->spk;
+    info->smask |= GPVTG;
+}
diff --git a/lib/pud/nmealib/src/parser.c b/lib/pud/nmealib/src/parser.c
new file mode 100644
index 0000000..4884321
--- /dev/null
+++ b/lib/pud/nmealib/src/parser.c
@@ -0,0 +1,419 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file parser.h
+ */
+
+#include <nmea/parser.h>
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <nmea/config.h>
+#include <nmea/context.h>
+#include <nmea/parse.h>
+#include <nmea/sentence.h>
+
+typedef struct _nmeaParserNODE
+{
+    int packType;
+    void *pack;
+    struct _nmeaParserNODE *next_node;
+
+} nmeaParserNODE;
+
+/*
+ * high level
+ */
+
+/**
+ * \brief Initialization of parser object
+ * @return true (1) - success or false (0) - fail
+ */
+int nmea_parser_init(nmeaPARSER *parser)
+{
+    int resv = 0;
+    int buff_size = nmea_property()->parse_buff_size;
+
+    NMEA_ASSERT(parser);
+
+    if(buff_size < NMEA_MIN_PARSEBUFF)
+        buff_size = NMEA_MIN_PARSEBUFF;
+
+    memset(parser, 0, sizeof(nmeaPARSER));
+
+    if(0 == (parser->buffer = malloc(buff_size)))
+        nmea_error("Insufficient memory!");
+    else
+    {
+        parser->buff_size = buff_size;
+        resv = 1;
+    }    
+
+    return resv;
+}
+
+/**
+ * \brief Destroy parser object
+ */
+void nmea_parser_destroy(nmeaPARSER *parser)
+{
+    NMEA_ASSERT(parser);
+    if (parser->buffer) {
+    	free(parser->buffer);
+    	parser->buffer = NULL;
+    }
+    nmea_parser_queue_clear(parser);
+    memset(parser, 0, sizeof(nmeaPARSER));
+}
+
+/**
+ * \brief Analysis of buffer and put results to information structure
+ * @return Number of packets wos parsed
+ */
+int nmea_parse(    
+    nmeaPARSER *parser,
+    const char *buff, int buff_sz,
+    nmeaINFO *info
+    )
+{
+    int ptype, nread = 0;
+    void *pack = 0;
+
+    NMEA_ASSERT(parser && parser->buffer);
+
+    nmea_parser_push(parser, buff, buff_sz);
+
+    while(GPNON != (ptype = nmea_parser_pop(parser, &pack)))
+    {
+        nread++;
+
+        switch(ptype)
+        {
+        case GPGGA:
+            nmea_GPGGA2info((nmeaGPGGA *)pack, info);
+            break;
+        case GPGSA:
+            nmea_GPGSA2info((nmeaGPGSA *)pack, info);
+            break;
+        case GPGSV:
+            nmea_GPGSV2info((nmeaGPGSV *)pack, info);
+            break;
+        case GPRMC:
+            nmea_GPRMC2info((nmeaGPRMC *)pack, info);
+            break;
+        case GPVTG:
+            nmea_GPVTG2info((nmeaGPVTG *)pack, info);
+            break;
+        default:
+            break;
+        };
+
+        free(pack);
+    }
+
+    return nread;
+}
+
+/*
+ * low level
+ */
+
+int nmea_parser_real_push(nmeaPARSER *parser, const char *buff, int buff_sz)
+{
+    int nparsed = 0, crc, sen_sz, ptype;
+    nmeaParserNODE *node = 0;
+
+    NMEA_ASSERT(parser && parser->buffer);
+
+    /* clear unuse buffer (for debug) */
+    /*
+    memset(
+        parser->buffer + parser->buff_use, 0,
+        parser->buff_size - parser->buff_use
+        );
+        */
+
+    /* add */
+    if(parser->buff_use + buff_sz >= parser->buff_size)
+        nmea_parser_buff_clear(parser);
+
+    memcpy(parser->buffer + parser->buff_use, buff, buff_sz);
+    parser->buff_use += buff_sz;
+
+    /* parse */
+    for(;;node = 0)
+    {
+        sen_sz = nmea_find_tail(
+            (const char *)parser->buffer + nparsed,
+            (int)parser->buff_use - nparsed, &crc);
+
+        if(!sen_sz)
+        {
+            if(nparsed)
+                memcpy(
+                parser->buffer,
+                parser->buffer + nparsed,
+                parser->buff_use -= nparsed);
+            break;
+        }
+        else if(crc >= 0)
+        {
+            ptype = nmea_pack_type(
+                (const char *)parser->buffer + nparsed + 1,
+                parser->buff_use - nparsed - 1);
+
+            if(0 == (node = malloc(sizeof(nmeaParserNODE))))
+                goto mem_fail;
+
+            node->pack = 0;
+
+            switch(ptype)
+            {
+            case GPGGA:
+                if(0 == (node->pack = malloc(sizeof(nmeaGPGGA))))
+                    goto mem_fail;
+                node->packType = GPGGA;
+                if(!nmea_parse_GPGGA(
+                    (const char *)parser->buffer + nparsed,
+                    sen_sz, (nmeaGPGGA *)node->pack))
+                {
+                    free(node);
+                    node = 0;
+                }
+                break;
+            case GPGSA:
+                if(0 == (node->pack = malloc(sizeof(nmeaGPGSA))))
+                    goto mem_fail;
+                node->packType = GPGSA;
+                if(!nmea_parse_GPGSA(
+                    (const char *)parser->buffer + nparsed,
+                    sen_sz, (nmeaGPGSA *)node->pack))
+                {
+                    free(node);
+                    node = 0;
+                }
+                break;
+            case GPGSV:
+                if(0 == (node->pack = malloc(sizeof(nmeaGPGSV))))
+                    goto mem_fail;
+                node->packType = GPGSV;
+                if(!nmea_parse_GPGSV(
+                    (const char *)parser->buffer + nparsed,
+                    sen_sz, (nmeaGPGSV *)node->pack))
+                {
+                    free(node);
+                    node = 0;
+                }
+                break;
+            case GPRMC:
+                if(0 == (node->pack = malloc(sizeof(nmeaGPRMC))))
+                    goto mem_fail;
+                node->packType = GPRMC;
+                if(!nmea_parse_GPRMC(
+                    (const char *)parser->buffer + nparsed,
+                    sen_sz, (nmeaGPRMC *)node->pack))
+                {
+                    free(node);
+                    node = 0;
+                }
+                break;
+            case GPVTG:
+                if(0 == (node->pack = malloc(sizeof(nmeaGPVTG))))
+                    goto mem_fail;
+                node->packType = GPVTG;
+                if(!nmea_parse_GPVTG(
+                    (const char *)parser->buffer + nparsed,
+                    sen_sz, (nmeaGPVTG *)node->pack))
+                {
+                    free(node);
+                    node = 0;
+                }
+                break;
+            default:
+                free(node);
+                node = 0;
+                break;
+            };
+
+            if(node)
+            {
+                if(parser->end_node)
+                    ((nmeaParserNODE *)parser->end_node)->next_node = node;
+                parser->end_node = node;
+                if(!parser->top_node)
+                    parser->top_node = node;
+                node->next_node = 0;
+            }
+        }
+
+        nparsed += sen_sz;
+    }
+
+    return nparsed;
+
+mem_fail:
+    if(node)
+        free(node);
+
+    nmea_error("Insufficient memory!");
+
+    return -1;
+}
+
+/**
+ * \brief Analysis of buffer and keep results into parser
+ * @return Number of bytes wos parsed from buffer
+ */
+int nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz)
+{
+    int nparse, nparsed = 0;
+
+    do
+    {
+        if(buff_sz > parser->buff_size)
+            nparse = parser->buff_size;
+        else
+            nparse = buff_sz;
+
+        nparsed += nmea_parser_real_push(
+            parser, buff, nparse);
+
+        buff_sz -= nparse;
+
+    } while(buff_sz);
+
+    return nparsed;
+}
+
+/**
+ * \brief Get type of top packet keeped into parser
+ * @return Type of packet
+ * @see nmeaPACKTYPE
+ */
+int nmea_parser_top(nmeaPARSER *parser)
+{
+    int retval = GPNON;
+    nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
+
+    NMEA_ASSERT(parser && parser->buffer);
+
+    if(node)
+        retval = node->packType;
+
+    return retval;
+}
+
+/**
+ * \brief Withdraw top packet from parser
+ * @return Received packet type
+ * @see nmeaPACKTYPE
+ */
+int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr)
+{
+    int retval = GPNON;
+    nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
+
+    NMEA_ASSERT(parser && parser->buffer);
+
+    if(node)
+    {
+        *pack_ptr = node->pack;
+        retval = node->packType;
+        parser->top_node = node->next_node;
+        if(!parser->top_node)
+            parser->end_node = 0;
+        free(node);
+    }
+
+    return retval;
+}
+
+/**
+ * \brief Get top packet from parser without withdraw
+ * @return Received packet type
+ * @see nmeaPACKTYPE
+ */
+int nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr)
+{
+    int retval = GPNON;
+    nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
+
+    NMEA_ASSERT(parser && parser->buffer);
+
+    if(node)
+    {
+        *pack_ptr = node->pack;
+        retval = node->packType;
+    }
+
+    return retval;
+}
+
+/**
+ * \brief Delete top packet from parser
+ * @return Deleted packet type
+ * @see nmeaPACKTYPE
+ */
+int nmea_parser_drop(nmeaPARSER *parser)
+{
+    int retval = GPNON;
+    nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
+
+    NMEA_ASSERT(parser && parser->buffer);
+
+    if(node)
+    {
+        if(node->pack)
+            free(node->pack);
+        retval = node->packType;
+        parser->top_node = node->next_node;
+        if(!parser->top_node)
+            parser->end_node = 0;
+        free(node);
+    }
+
+    return retval;
+}
+
+/**
+ * \brief Clear cache of parser
+ * @return true (1) - success
+ */
+int nmea_parser_buff_clear(nmeaPARSER *parser)
+{
+    NMEA_ASSERT(parser && parser->buffer);
+    parser->buff_use = 0;
+    return 1;
+}
+
+/**
+ * \brief Clear packets queue into parser
+ * @return true (1) - success
+ */
+int nmea_parser_queue_clear(nmeaPARSER *parser)
+{
+    NMEA_ASSERT(parser);
+    while(parser->top_node)
+        nmea_parser_drop(parser);
+    return 1;
+}
diff --git a/lib/pud/nmealib/src/sentence.c b/lib/pud/nmealib/src/sentence.c
new file mode 100644
index 0000000..cf98c72
--- /dev/null
+++ b/lib/pud/nmealib/src/sentence.c
@@ -0,0 +1,64 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/sentence.h>
+
+#include <string.h>
+
+void nmea_zero_GPGGA(nmeaGPGGA *pack)
+{
+    memset(pack, 0, sizeof(nmeaGPGGA));
+    nmea_time_now(&pack->utc);
+    pack->ns = 'N';
+    pack->ew = 'E';
+    pack->elv_units = 'M';
+    pack->diff_units = 'M';
+}
+
+void nmea_zero_GPGSA(nmeaGPGSA *pack)
+{
+    memset(pack, 0, sizeof(nmeaGPGSA));
+    pack->fix_mode = 'A';
+    pack->fix_type = NMEA_FIX_BAD;
+}
+
+void nmea_zero_GPGSV(nmeaGPGSV *pack)
+{
+    memset(pack, 0, sizeof(nmeaGPGSV));
+}
+
+void nmea_zero_GPRMC(nmeaGPRMC *pack)
+{
+    memset(pack, 0, sizeof(nmeaGPRMC));
+    nmea_time_now(&pack->utc);
+    pack->status = 'V';
+    pack->ns = 'N';
+    pack->ew = 'E';
+    pack->declin_ew = 'E';
+}
+
+void nmea_zero_GPVTG(nmeaGPVTG *pack)
+{
+    memset(pack, 0, sizeof(nmeaGPVTG));
+    pack->dir_t = 'T';
+    pack->dec_m = 'M';
+    pack->spn_n = 'N';
+    pack->spk_k = 'K';
+}
diff --git a/lib/pud/nmealib/src/time.c b/lib/pud/nmealib/src/time.c
new file mode 100644
index 0000000..18d6be8
--- /dev/null
+++ b/lib/pud/nmealib/src/time.c
@@ -0,0 +1,41 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/time.h>
+
+#include <stddef.h>
+#include <time.h>
+#include <sys/time.h>
+
+void nmea_time_now(nmeaTIME *stm) {
+	struct timeval tp;
+	struct tm tt;
+
+	gettimeofday(&tp, NULL);
+	gmtime_r(&tp.tv_sec, &tt);
+
+	stm->year = tt.tm_year;
+	stm->mon = tt.tm_mon;
+	stm->day = tt.tm_mday;
+	stm->hour = tt.tm_hour;
+	stm->min = tt.tm_min;
+	stm->sec = tt.tm_sec;
+	stm->hsec = (tp.tv_usec / 10000);
+}
diff --git a/lib/pud/nmealib/src/tok.c b/lib/pud/nmealib/src/tok.c
new file mode 100644
index 0000000..c9126a0
--- /dev/null
+++ b/lib/pud/nmealib/src/tok.c
@@ -0,0 +1,270 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2008 Timur Sinitsyn
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \file tok.h */
+
+#include <nmea/tok.h>
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <nmea/config.h>
+
+#define NMEA_TOKS_COMPARE   (1)
+#define NMEA_TOKS_PERCENT   (2)
+#define NMEA_TOKS_WIDTH     (3)
+#define NMEA_TOKS_TYPE      (4)
+
+#define NMEA_CONVSTR_BUF    (256)
+
+/**
+ * \brief Calculate control sum of binary buffer
+ */
+int nmea_calc_crc(const char *buff, int buff_sz)
+{
+    int chsum = 0,
+        it;
+
+    for(it = 0; it < buff_sz; ++it)
+        chsum ^= (int)buff[it];
+
+    return chsum;
+}
+
+/**
+ * \brief Convert string to number
+ */
+int nmea_atoi(const char *str, int str_sz, int radix)
+{
+    char *tmp_ptr;
+    char buff[NMEA_CONVSTR_BUF];
+    int res = 0;
+
+    if(str_sz < NMEA_CONVSTR_BUF)
+    {
+        memcpy(&buff[0], str, str_sz);
+        buff[str_sz] = '\0';
+        res = strtol(&buff[0], &tmp_ptr, radix);
+    }
+
+    return res;
+}
+
+/**
+ * \brief Convert string to fraction number
+ */
+double nmea_atof(const char *str, int str_sz)
+{
+    char *tmp_ptr;
+    char buff[NMEA_CONVSTR_BUF];
+    double res = 0;
+
+    if(str_sz < NMEA_CONVSTR_BUF)
+    {
+        memcpy(&buff[0], str, str_sz);
+        buff[str_sz] = '\0';
+        res = strtod(&buff[0], &tmp_ptr);
+    }
+
+    return res;
+}
+
+/**
+ * \brief Formating string (like standart printf) with CRC tail (*CRC)
+ */
+int nmea_printf(char *buff, int buff_sz, const char *format, ...)
+{
+    int retval, add = 0;
+    va_list arg_ptr;
+
+    if(buff_sz <= 0)
+        return 0;
+
+    va_start(arg_ptr, format);
+
+    retval = NMEA_POSIX(vsnprintf)(buff, buff_sz, format, arg_ptr);
+
+    if(retval > 0)
+    {
+        add = NMEA_POSIX(snprintf)(
+            buff + retval, buff_sz - retval, "*%02x\r\n",
+            nmea_calc_crc(buff + 1, retval - 1));
+    }
+
+    retval += add;
+
+    if(retval < 0 || retval > buff_sz)
+    {
+        memset(buff, ' ', buff_sz);
+        retval = buff_sz;
+    }
+
+    va_end(arg_ptr);
+
+    return retval;
+}
+
+/**
+ * \brief Analyse string (specificate for NMEA sentences)
+ */
+int nmea_scanf(const char *buff, int buff_sz, const char *format, ...)
+{
+    const char *beg_tok;
+    const char *end_buf = buff + buff_sz;
+
+    va_list arg_ptr;
+    int tok_type = NMEA_TOKS_COMPARE;
+    int width = 0;
+    const char *beg_fmt = 0;
+    int snum = 0, unum = 0;
+
+    int tok_count = 0;
+    void *parg_target;
+
+    va_start(arg_ptr, format);
+    
+    for(; *format && buff < end_buf; ++format)
+    {
+        switch(tok_type)
+        {
+        case NMEA_TOKS_COMPARE:
+            if('%' == *format)
+                tok_type = NMEA_TOKS_PERCENT;
+            else if(*buff++ != *format)
+                goto fail;
+            break;
+        case NMEA_TOKS_PERCENT:
+            width = 0;
+            beg_fmt = format;
+            tok_type = NMEA_TOKS_WIDTH;
+            /* no break */
+        case NMEA_TOKS_WIDTH:
+            if(isdigit(*format))
+                break;
+            {
+                tok_type = NMEA_TOKS_TYPE;
+                if(format > beg_fmt)
+                    width = nmea_atoi(beg_fmt, (int)(format - beg_fmt), 10);
+            }
+            /* no break */
+        case NMEA_TOKS_TYPE:
+            beg_tok = buff;
+
+            if(!width && ('c' == *format || 'C' == *format) && *buff != format[1])
+                width = 1;
+
+            if(width)
+            {
+                if(buff + width <= end_buf)
+                    buff += width;
+                else
+                    goto fail;
+            }
+            else
+            {
+                if(!format[1] || (0 == (buff = (char *)memchr(buff, format[1], end_buf - buff))))
+                    buff = end_buf;
+            }
+
+            if(buff > end_buf)
+                goto fail;
+
+            tok_type = NMEA_TOKS_COMPARE;
+            tok_count++;
+
+            parg_target = 0; width = (int)(buff - beg_tok);
+
+            switch(*format)
+            {
+            case 'c':
+            case 'C':
+                parg_target = (void *)va_arg(arg_ptr, char *);
+                if(width && 0 != (parg_target))
+                    *((char *)parg_target) = *beg_tok;
+                break;
+            case 's':
+            case 'S':
+                parg_target = (void *)va_arg(arg_ptr, char *);
+                if(width && 0 != (parg_target))
+                {
+                    memcpy(parg_target, beg_tok, width);
+                    ((char *)parg_target)[width] = '\0';
+                }
+                break;
+            case 'f':
+            case 'g':
+            case 'G':
+            case 'e':
+            case 'E':
+                parg_target = (void *)va_arg(arg_ptr, double *);
+                if(width && 0 != (parg_target))
+                    *((double *)parg_target) = nmea_atof(beg_tok, width);
+                break;
+            default:
+                break;
+            };
+
+            if(parg_target)
+                break;
+            if(0 == (parg_target = (void *)va_arg(arg_ptr, int *)))
+                break;
+            if(!width)
+                break;
+
+            switch(*format)
+            {
+            case 'd':
+            case 'i':
+                snum = nmea_atoi(beg_tok, width, 10);
+                memcpy(parg_target, &snum, sizeof(int));
+                break;
+            case 'u':
+                unum = nmea_atoi(beg_tok, width, 10);
+                memcpy(parg_target, &unum, sizeof(unsigned int));
+                break;
+            case 'x':
+            case 'X':
+                unum = nmea_atoi(beg_tok, width, 16);
+                memcpy(parg_target, &unum, sizeof(unsigned int));
+                break;
+            case 'o':
+                unum = nmea_atoi(beg_tok, width, 8);
+                memcpy(parg_target, &unum, sizeof(unsigned int));
+                break;
+            default:
+                goto fail;
+            };
+
+            break;
+
+        default:
+            break;
+        };
+    }
+
+fail:
+
+    va_end(arg_ptr);
+
+    return tok_count;
+}
diff --git a/lib/pud/nmealib/src/util.c b/lib/pud/nmealib/src/util.c
new file mode 100644
index 0000000..45e57e0
--- /dev/null
+++ b/lib/pud/nmealib/src/util.c
@@ -0,0 +1,85 @@
+/*
+ * This file is part of nmealib.
+ *
+ * Copyright (c) 2011 Ferry Huberts
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nmea/util.h>
+
+#include <string.h>
+#include <stdio.h>
+
+/**
+ * Determine whether the given string contains characters that are not allowed
+ * for fields in an NMEA string.
+ *
+ * @param str
+ * The string to check
+ * @param strName
+ * The name of the string to report when invalid characters are encountered
+ * @param report
+ * A pointer to a buffer in which to place the report string when an invalid
+ * nmea character is detected
+ * @param reportSize
+ * The size of the report buffer
+ *
+ * @return
+ * - true when the string has invalid characters
+ * - false otherwise
+ */
+bool nmea_string_has_invalid_chars(const char * str, const char * strName,
+		char * report, size_t reportSize) {
+	static const char invalidChars[] = { '$', '*', ',', '!', '\\', '^', '~' };
+	static const char * invalidCharsNames[] = { "sentence delimiter ($)",
+			"checksum field delimiter (*)", "comma (,)", "exclamation mark (!)",
+			"backslash (\\)", "^ (^)", "tilde (~)" };
+
+	size_t i;
+	size_t j;
+
+	if (!str) {
+		return false;
+	}
+
+	for (i = 0; i < strlen(str); i++) {
+		char c = str[i];
+
+		if ((c < 32) || (c > 126)) {
+			if (report) {
+				snprintf((char*) report, reportSize, "Configured %s (%s),"
+						" character %lu, can not contain non-printable"
+						" characters (codes outside the range [32, 126])",
+						strName, str, (unsigned long)i + 1);
+				report[reportSize - 1] = '\0';
+			}
+			return true;
+		}
+
+		for (j = 0; j < sizeof(invalidChars); j++) {
+			if (c == invalidChars[j]) {
+				if (report) {
+					snprintf((char *) report, reportSize, "Configured %s (%s),"
+							" character %lu, can not contain %s characters",
+							strName, str, (unsigned long)i + 1, invalidCharsNames[j]);
+					report[reportSize - 1] = '\0';
+				}
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
-- 
1.7.7.6





More information about the Olsr-dev mailing list