Import NMEAP 0.3 library.
authorasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Fri, 2 Oct 2009 15:12:47 +0000 (15:12 +0000)
committerasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Fri, 2 Oct 2009 15:12:47 +0000 (15:12 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3002 38d2e660-2303-0410-9eaa-f027e97ec537

17 files changed:
bertos/net/nmeap/COPYING [new file with mode: 0644]
bertos/net/nmeap/Doxyfile [new file with mode: 0644]
bertos/net/nmeap/Makefile [new file with mode: 0644]
bertos/net/nmeap/README [new file with mode: 0644]
bertos/net/nmeap/doc/tutorial.html [new file with mode: 0644]
bertos/net/nmeap/inc/nmeap.h [new file with mode: 0644]
bertos/net/nmeap/inc/nmeap_def.h [new file with mode: 0644]
bertos/net/nmeap/src/Makefile [new file with mode: 0644]
bertos/net/nmeap/src/nmeap.mak [new file with mode: 0644]
bertos/net/nmeap/src/nmeap01.c [new file with mode: 0644]
bertos/net/nmeap/tst/Makefile [new file with mode: 0644]
bertos/net/nmeap/tst/test1.c [new file with mode: 0644]
bertos/net/nmeap/tst/test2.c [new file with mode: 0644]
bertos/net/nmeap/tst/test3.c [new file with mode: 0644]
bertos/net/nmeap/tst/tst.mak [new file with mode: 0644]
bertos/net/nmeap/tst/wingps.c [new file with mode: 0644]
bertos/net/nmeap/win32.mak [new file with mode: 0644]

diff --git a/bertos/net/nmeap/COPYING b/bertos/net/nmeap/COPYING
new file mode 100644 (file)
index 0000000..9c54246
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License:
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+         this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright 
+         notice, this list of conditions and the following disclaimer in 
+         the documentation and/or other materials provided with the distribution.
+    * Neither the name of the copyright holders nor the names of its 
+         contributors may be used to endorse or promote products derived from 
+         this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
diff --git a/bertos/net/nmeap/Doxyfile b/bertos/net/nmeap/Doxyfile
new file mode 100644 (file)
index 0000000..aae008e
--- /dev/null
@@ -0,0 +1,1153 @@
+# Doxyfile 1.3.8\r
+\r
+# This file describes the settings to be used by the documentation system\r
+# doxygen (www.doxygen.org) for a project\r
+#\r
+# All text after a hash (#) is considered a comment and will be ignored\r
+# The format is:\r
+#       TAG = value [value, ...]\r
+# For lists items can also be appended using:\r
+#       TAG += value [value, ...]\r
+# Values that contain spaces should be placed between quotes (" ")\r
+\r
+#---------------------------------------------------------------------------\r
+# Project related configuration options\r
+#---------------------------------------------------------------------------\r
+\r
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded \r
+# by quotes) that should identify the project.\r
+\r
+PROJECT_NAME           = NMEAP\r
+\r
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. \r
+# This could be handy for archiving the generated documentation or \r
+# if some version control system is used.\r
+\r
+PROJECT_NUMBER         = 0.1\r
+\r
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) \r
+# base path where the generated documentation will be put. \r
+# If a relative path is entered, it will be relative to the location \r
+# where doxygen was started. If left blank the current directory will be used.\r
+\r
+OUTPUT_DIRECTORY       = doc\r
+\r
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create \r
+# 4096 sub-directories (in 2 levels) under the output directory of each output \r
+# format and will distribute the generated files over these directories. \r
+# Enabling this option can be useful when feeding doxygen a huge amount of source \r
+# files, where putting all generated files in the same directory would otherwise \r
+# cause performance problems for the file system.\r
+\r
+CREATE_SUBDIRS         = NO\r
+\r
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all \r
+# documentation generated by doxygen is written. Doxygen will use this \r
+# information to generate all constant output in the proper language. \r
+# The default language is English, other supported languages are: \r
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, \r
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, \r
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, \r
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, \r
+# Swedish, and Ukrainian.\r
+\r
+OUTPUT_LANGUAGE        = English\r
+\r
+# This tag can be used to specify the encoding used in the generated output. \r
+# The encoding is not always determined by the language that is chosen, \r
+# but also whether or not the output is meant for Windows or non-Windows users. \r
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES \r
+# forces the Windows encoding (this is the default for the Windows binary), \r
+# whereas setting the tag to NO uses a Unix-style encoding (the default for \r
+# all platforms other than Windows).\r
+\r
+USE_WINDOWS_ENCODING   = NO\r
+\r
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will \r
+# include brief member descriptions after the members that are listed in \r
+# the file and class documentation (similar to JavaDoc). \r
+# Set to NO to disable this.\r
+\r
+BRIEF_MEMBER_DESC      = YES\r
+\r
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend \r
+# the brief description of a member or function before the detailed description. \r
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the \r
+# brief descriptions will be completely suppressed.\r
+\r
+REPEAT_BRIEF           = YES\r
+\r
+# This tag implements a quasi-intelligent brief description abbreviator \r
+# that is used to form the text in various listings. Each string \r
+# in this list, if found as the leading text of the brief description, will be \r
+# stripped from the text and the result after processing the whole list, is used \r
+# as the annotated text. Otherwise, the brief description is used as-is. If left \r
+# blank, the following values are used ("$name" is automatically replaced with the \r
+# name of the entity): "The $name class" "The $name widget" "The $name file" \r
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"\r
+\r
+ABBREVIATE_BRIEF       = \r
+\r
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then \r
+# Doxygen will generate a detailed section even if there is only a brief \r
+# description.\r
+\r
+ALWAYS_DETAILED_SEC    = NO\r
+\r
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited \r
+# members of a class in the documentation of that class as if those members were \r
+# ordinary class members. Constructors, destructors and assignment operators of \r
+# the base classes will not be shown.\r
+\r
+INLINE_INHERITED_MEMB  = NO\r
+\r
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full \r
+# path before files name in the file list and in the header files. If set \r
+# to NO the shortest path that makes the file name unique will be used.\r
+\r
+FULL_PATH_NAMES        = NO\r
+\r
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag \r
+# can be used to strip a user-defined part of the path. Stripping is \r
+# only done if one of the specified strings matches the left-hand part of \r
+# the path. The tag can be used to show relative paths in the file list. \r
+# If left blank the directory from which doxygen is run is used as the \r
+# path to strip.\r
+\r
+STRIP_FROM_PATH        = \r
+\r
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of \r
+# the path mentioned in the documentation of a class, which tells \r
+# the reader which header file to include in order to use a class. \r
+# If left blank only the name of the header file containing the class \r
+# definition is used. Otherwise one should specify the include paths that \r
+# are normally passed to the compiler using the -I flag.\r
+\r
+STRIP_FROM_INC_PATH    = \r
+\r
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter \r
+# (but less readable) file names. This can be useful is your file systems \r
+# doesn't support long names like on DOS, Mac, or CD-ROM.\r
+\r
+SHORT_NAMES            = NO\r
+\r
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen \r
+# will interpret the first line (until the first dot) of a JavaDoc-style \r
+# comment as the brief description. If set to NO, the JavaDoc \r
+# comments will behave just like the Qt-style comments (thus requiring an \r
+# explicit @brief command for a brief description.\r
+\r
+JAVADOC_AUTOBRIEF      = NO\r
+\r
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen \r
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// \r
+# comments) as a brief description. This used to be the default behaviour. \r
+# The new default is to treat a multi-line C++ comment block as a detailed \r
+# description. Set this tag to YES if you prefer the old behaviour instead.\r
+\r
+MULTILINE_CPP_IS_BRIEF = NO\r
+\r
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen \r
+# will output the detailed description near the top, like JavaDoc.\r
+# If set to NO, the detailed description appears after the member \r
+# documentation.\r
+\r
+DETAILS_AT_TOP         = NO\r
+\r
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented \r
+# member inherits the documentation from any documented member that it \r
+# re-implements.\r
+\r
+INHERIT_DOCS           = YES\r
+\r
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC \r
+# tag is set to YES, then doxygen will reuse the documentation of the first \r
+# member in the group (if any) for the other members of the group. By default \r
+# all members of a group must be documented explicitly.\r
+\r
+DISTRIBUTE_GROUP_DOC   = NO\r
+\r
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. \r
+# Doxygen uses this value to replace tabs by spaces in code fragments.\r
+\r
+TAB_SIZE               = 8\r
+\r
+# This tag can be used to specify a number of aliases that acts \r
+# as commands in the documentation. An alias has the form "name=value". \r
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to \r
+# put the command \sideeffect (or @sideeffect) in the documentation, which \r
+# will result in a user-defined paragraph with heading "Side Effects:". \r
+# You can put \n's in the value part of an alias to insert newlines.\r
+\r
+ALIASES                = \r
+\r
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources \r
+# only. Doxygen will then generate output that is more tailored for C. \r
+# For instance, some of the names that are used will be different. The list \r
+# of all members will be omitted, etc.\r
+\r
+OPTIMIZE_OUTPUT_FOR_C  = YES\r
+\r
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources \r
+# only. Doxygen will then generate output that is more tailored for Java. \r
+# For instance, namespaces will be presented as packages, qualified scopes \r
+# will look different, etc.\r
+\r
+OPTIMIZE_OUTPUT_JAVA   = NO\r
+\r
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of \r
+# the same type (for instance a group of public functions) to be put as a \r
+# subgroup of that type (e.g. under the Public Functions section). Set it to \r
+# NO to prevent subgrouping. Alternatively, this can be done per class using \r
+# the \nosubgrouping command.\r
+\r
+SUBGROUPING            = YES\r
+\r
+#---------------------------------------------------------------------------\r
+# Build related configuration options\r
+#---------------------------------------------------------------------------\r
+\r
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in \r
+# documentation are documented, even if no documentation was available. \r
+# Private class members and static file members will be hidden unless \r
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES\r
+\r
+EXTRACT_ALL            = YES\r
+\r
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class \r
+# will be included in the documentation.\r
+\r
+EXTRACT_PRIVATE        = YES\r
+\r
+# If the EXTRACT_STATIC tag is set to YES all static members of a file \r
+# will be included in the documentation.\r
+\r
+EXTRACT_STATIC         = YES\r
+\r
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) \r
+# defined locally in source files will be included in the documentation. \r
+# If set to NO only classes defined in header files are included.\r
+\r
+EXTRACT_LOCAL_CLASSES  = YES\r
+\r
+# This flag is only useful for Objective-C code. When set to YES local \r
+# methods, which are defined in the implementation section but not in \r
+# the interface are included in the documentation. \r
+# If set to NO (the default) only methods in the interface are included.\r
+\r
+EXTRACT_LOCAL_METHODS  = NO\r
+\r
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all \r
+# undocumented members of documented classes, files or namespaces. \r
+# If set to NO (the default) these members will be included in the \r
+# various overviews, but no documentation section is generated. \r
+# This option has no effect if EXTRACT_ALL is enabled.\r
+\r
+HIDE_UNDOC_MEMBERS     = NO\r
+\r
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all \r
+# undocumented classes that are normally visible in the class hierarchy. \r
+# If set to NO (the default) these classes will be included in the various \r
+# overviews. This option has no effect if EXTRACT_ALL is enabled.\r
+\r
+HIDE_UNDOC_CLASSES     = NO\r
+\r
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all \r
+# friend (class|struct|union) declarations. \r
+# If set to NO (the default) these declarations will be included in the \r
+# documentation.\r
+\r
+HIDE_FRIEND_COMPOUNDS  = NO\r
+\r
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any \r
+# documentation blocks found inside the body of a function. \r
+# If set to NO (the default) these blocks will be appended to the \r
+# function's detailed documentation block.\r
+\r
+HIDE_IN_BODY_DOCS      = NO\r
+\r
+# The INTERNAL_DOCS tag determines if documentation \r
+# that is typed after a \internal command is included. If the tag is set \r
+# to NO (the default) then the documentation will be excluded. \r
+# Set it to YES to include the internal documentation.\r
+\r
+INTERNAL_DOCS          = NO\r
+\r
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate \r
+# file names in lower-case letters. If set to YES upper-case letters are also \r
+# allowed. This is useful if you have classes or files whose names only differ \r
+# in case and if your file system supports case sensitive file names. Windows \r
+# and Mac users are advised to set this option to NO.\r
+\r
+CASE_SENSE_NAMES       = NO\r
+\r
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen \r
+# will show members with their full class and namespace scopes in the \r
+# documentation. If set to YES the scope will be hidden.\r
+\r
+HIDE_SCOPE_NAMES       = NO\r
+\r
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen \r
+# will put a list of the files that are included by a file in the documentation \r
+# of that file.\r
+\r
+SHOW_INCLUDE_FILES     = YES\r
+\r
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] \r
+# is inserted in the documentation for inline members.\r
+\r
+INLINE_INFO            = YES\r
+\r
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen \r
+# will sort the (detailed) documentation of file and class members \r
+# alphabetically by member name. If set to NO the members will appear in \r
+# declaration order.\r
+\r
+SORT_MEMBER_DOCS       = YES\r
+\r
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the \r
+# brief documentation of file, namespace and class members alphabetically \r
+# by member name. If set to NO (the default) the members will appear in \r
+# declaration order.\r
+\r
+SORT_BRIEF_DOCS        = NO\r
+\r
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be \r
+# sorted by fully-qualified names, including namespaces. If set to \r
+# NO (the default), the class list will be sorted only by class name, \r
+# not including the namespace part. \r
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\r
+# Note: This option applies only to the class list, not to the \r
+# alphabetical list.\r
+\r
+SORT_BY_SCOPE_NAME     = NO\r
+\r
+# The GENERATE_TODOLIST tag can be used to enable (YES) or \r
+# disable (NO) the todo list. This list is created by putting \todo \r
+# commands in the documentation.\r
+\r
+GENERATE_TODOLIST      = YES\r
+\r
+# The GENERATE_TESTLIST tag can be used to enable (YES) or \r
+# disable (NO) the test list. This list is created by putting \test \r
+# commands in the documentation.\r
+\r
+GENERATE_TESTLIST      = YES\r
+\r
+# The GENERATE_BUGLIST tag can be used to enable (YES) or \r
+# disable (NO) the bug list. This list is created by putting \bug \r
+# commands in the documentation.\r
+\r
+GENERATE_BUGLIST       = YES\r
+\r
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or \r
+# disable (NO) the deprecated list. This list is created by putting \r
+# \deprecated commands in the documentation.\r
+\r
+GENERATE_DEPRECATEDLIST= YES\r
+\r
+# The ENABLED_SECTIONS tag can be used to enable conditional \r
+# documentation sections, marked by \if sectionname ... \endif.\r
+\r
+ENABLED_SECTIONS       = \r
+\r
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines \r
+# the initial value of a variable or define consists of for it to appear in \r
+# the documentation. If the initializer consists of more lines than specified \r
+# here it will be hidden. Use a value of 0 to hide initializers completely. \r
+# The appearance of the initializer of individual variables and defines in the \r
+# documentation can be controlled using \showinitializer or \hideinitializer \r
+# command in the documentation regardless of this setting.\r
+\r
+MAX_INITIALIZER_LINES  = 30\r
+\r
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated \r
+# at the bottom of the documentation of classes and structs. If set to YES the \r
+# list will mention the files that were used to generate the documentation.\r
+\r
+SHOW_USED_FILES        = YES\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to warning and progress messages\r
+#---------------------------------------------------------------------------\r
+\r
+# The QUIET tag can be used to turn on/off the messages that are generated \r
+# by doxygen. Possible values are YES and NO. If left blank NO is used.\r
+\r
+QUIET                  = NO\r
+\r
+# The WARNINGS tag can be used to turn on/off the warning messages that are \r
+# generated by doxygen. Possible values are YES and NO. If left blank \r
+# NO is used.\r
+\r
+WARNINGS               = YES\r
+\r
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings \r
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will \r
+# automatically be disabled.\r
+\r
+WARN_IF_UNDOCUMENTED   = YES\r
+\r
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for \r
+# potential errors in the documentation, such as not documenting some \r
+# parameters in a documented function, or documenting parameters that \r
+# don't exist or using markup commands wrongly.\r
+\r
+WARN_IF_DOC_ERROR      = YES\r
+\r
+# The WARN_FORMAT tag determines the format of the warning messages that \r
+# doxygen can produce. The string should contain the $file, $line, and $text \r
+# tags, which will be replaced by the file and line number from which the \r
+# warning originated and the warning text.\r
+\r
+WARN_FORMAT            = "$file:$line: $text"\r
+\r
+# The WARN_LOGFILE tag can be used to specify a file to which warning \r
+# and error messages should be written. If left blank the output is written \r
+# to stderr.\r
+\r
+WARN_LOGFILE           = \r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the input files\r
+#---------------------------------------------------------------------------\r
+\r
+# The INPUT tag can be used to specify the files and/or directories that contain \r
+# documented source files. You may enter file names like "myfile.cpp" or \r
+# directories like "/usr/src/myproject". Separate the files or directories \r
+# with spaces.\r
+\r
+INPUT                  = inc/nmeap.h\r
+\r
+# If the value of the INPUT tag contains directories, you can use the \r
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp \r
+# and *.h) to filter out the source-files in the directories. If left \r
+# blank the following patterns are tested: \r
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp \r
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm\r
+\r
+FILE_PATTERNS          = *.h\r
+\r
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories \r
+# should be searched for input files as well. Possible values are YES and NO. \r
+# If left blank NO is used.\r
+\r
+RECURSIVE              = YES\r
+\r
+# The EXCLUDE tag can be used to specify files and/or directories that should \r
+# excluded from the INPUT source files. This way you can easily exclude a \r
+# subdirectory from a directory tree whose root is specified with the INPUT tag.\r
+\r
+EXCLUDE                = \r
+\r
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories \r
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.\r
+\r
+EXCLUDE_SYMLINKS       = NO\r
+\r
+# If the value of the INPUT tag contains directories, you can use the \r
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude \r
+# certain files from those directories.\r
+\r
+EXCLUDE_PATTERNS       = \r
+\r
+# The EXAMPLE_PATH tag can be used to specify one or more files or \r
+# directories that contain example code fragments that are included (see \r
+# the \include command).\r
+\r
+EXAMPLE_PATH           = \r
+\r
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the \r
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp \r
+# and *.h) to filter out the source-files in the directories. If left \r
+# blank all files are included.\r
+\r
+EXAMPLE_PATTERNS       = \r
+\r
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be \r
+# searched for input files to be used with the \include or \dontinclude \r
+# commands irrespective of the value of the RECURSIVE tag. \r
+# Possible values are YES and NO. If left blank NO is used.\r
+\r
+EXAMPLE_RECURSIVE      = NO\r
+\r
+# The IMAGE_PATH tag can be used to specify one or more files or \r
+# directories that contain image that are included in the documentation (see \r
+# the \image command).\r
+\r
+IMAGE_PATH             = \r
+\r
+# The INPUT_FILTER tag can be used to specify a program that doxygen should \r
+# invoke to filter for each input file. Doxygen will invoke the filter program \r
+# by executing (via popen()) the command <filter> <input-file>, where <filter> \r
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an \r
+# input file. Doxygen will then use the output that the filter program writes \r
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be \r
+# ignored.\r
+\r
+INPUT_FILTER           = \r
+\r
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern \r
+# basis.  Doxygen will compare the file name with each pattern and apply the \r
+# filter if there is a match.  The filters are a list of the form: \r
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further \r
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER \r
+# is applied to all files.\r
+\r
+FILTER_PATTERNS        = \r
+\r
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using \r
+# INPUT_FILTER) will be used to filter the input files when producing source \r
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).\r
+\r
+FILTER_SOURCE_FILES    = NO\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to source browsing\r
+#---------------------------------------------------------------------------\r
+\r
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will \r
+# be generated. Documented entities will be cross-referenced with these sources. \r
+# Note: To get rid of all source code in the generated output, make sure also \r
+# VERBATIM_HEADERS is set to NO.\r
+\r
+SOURCE_BROWSER         = NO\r
+\r
+# Setting the INLINE_SOURCES tag to YES will include the body \r
+# of functions and classes directly in the documentation.\r
+\r
+INLINE_SOURCES         = NO\r
+\r
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct \r
+# doxygen to hide any special comment blocks from generated source code \r
+# fragments. Normal C and C++ comments will always remain visible.\r
+\r
+STRIP_CODE_COMMENTS    = NO\r
+\r
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) \r
+# then for each documented function all documented \r
+# functions referencing it will be listed.\r
+\r
+REFERENCED_BY_RELATION = YES\r
+\r
+# If the REFERENCES_RELATION tag is set to YES (the default) \r
+# then for each documented function all documented entities \r
+# called/used by that function will be listed.\r
+\r
+REFERENCES_RELATION    = YES\r
+\r
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen \r
+# will generate a verbatim copy of the header file for each class for \r
+# which an include is specified. Set to NO to disable this.\r
+\r
+VERBATIM_HEADERS       = YES\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the alphabetical class index\r
+#---------------------------------------------------------------------------\r
+\r
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index \r
+# of all compounds will be generated. Enable this if the project \r
+# contains a lot of classes, structs, unions or interfaces.\r
+\r
+ALPHABETICAL_INDEX     = NO\r
+\r
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then \r
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns \r
+# in which this list will be split (can be a number in the range [1..20])\r
+\r
+COLS_IN_ALPHA_INDEX    = 5\r
+\r
+# In case all classes in a project start with a common prefix, all \r
+# classes will be put under the same header in the alphabetical index. \r
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that \r
+# should be ignored while generating the index headers.\r
+\r
+IGNORE_PREFIX          = \r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the HTML output\r
+#---------------------------------------------------------------------------\r
+\r
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will \r
+# generate HTML output.\r
+\r
+GENERATE_HTML          = YES\r
+\r
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. \r
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be \r
+# put in front of it. If left blank `html' will be used as the default path.\r
+\r
+HTML_OUTPUT            = html\r
+\r
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for \r
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank \r
+# doxygen will generate files with .html extension.\r
+\r
+HTML_FILE_EXTENSION    = .html\r
+\r
+# The HTML_HEADER tag can be used to specify a personal HTML header for \r
+# each generated HTML page. If it is left blank doxygen will generate a \r
+# standard header.\r
+\r
+HTML_HEADER            = \r
+\r
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for \r
+# each generated HTML page. If it is left blank doxygen will generate a \r
+# standard footer.\r
+\r
+HTML_FOOTER            = \r
+\r
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading \r
+# style sheet that is used by each HTML page. It can be used to \r
+# fine-tune the look of the HTML output. If the tag is left blank doxygen \r
+# will generate a default style sheet. Note that doxygen will try to copy \r
+# the style sheet file to the HTML output directory, so don't put your own \r
+# stylesheet in the HTML output directory as well, or it will be erased!\r
+\r
+HTML_STYLESHEET        = \r
+\r
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, \r
+# files or namespaces will be aligned in HTML using tables. If set to \r
+# NO a bullet list will be used.\r
+\r
+HTML_ALIGN_MEMBERS     = YES\r
+\r
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files \r
+# will be generated that can be used as input for tools like the \r
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) \r
+# of the generated HTML documentation.\r
+\r
+GENERATE_HTMLHELP      = NO\r
+\r
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can \r
+# be used to specify the file name of the resulting .chm file. You \r
+# can add a path in front of the file if the result should not be \r
+# written to the html output directory.\r
+\r
+CHM_FILE               = \r
+\r
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can \r
+# be used to specify the location (absolute path including file name) of \r
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run \r
+# the HTML help compiler on the generated index.hhp.\r
+\r
+HHC_LOCATION           = \r
+\r
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag \r
+# controls if a separate .chi index file is generated (YES) or that \r
+# it should be included in the master .chm file (NO).\r
+\r
+GENERATE_CHI           = NO\r
+\r
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag \r
+# controls whether a binary table of contents is generated (YES) or a \r
+# normal table of contents (NO) in the .chm file.\r
+\r
+BINARY_TOC             = NO\r
+\r
+# The TOC_EXPAND flag can be set to YES to add extra items for group members \r
+# to the contents of the HTML help documentation and to the tree view.\r
+\r
+TOC_EXPAND             = NO\r
+\r
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at \r
+# top of each HTML page. The value NO (the default) enables the index and \r
+# the value YES disables it.\r
+\r
+DISABLE_INDEX          = NO\r
+\r
+# This tag can be used to set the number of enum values (range [1..20]) \r
+# that doxygen will group on one line in the generated HTML documentation.\r
+\r
+ENUM_VALUES_PER_LINE   = 4\r
+\r
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be\r
+# generated containing a tree-like index structure (just like the one that \r
+# is generated for HTML Help). For this to work a browser that supports \r
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, \r
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are \r
+# probably better off using the HTML help feature.\r
+\r
+GENERATE_TREEVIEW      = NO\r
+\r
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be \r
+# used to set the initial width (in pixels) of the frame in which the tree \r
+# is shown.\r
+\r
+TREEVIEW_WIDTH         = 250\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the LaTeX output\r
+#---------------------------------------------------------------------------\r
+\r
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will \r
+# generate Latex output.\r
+\r
+GENERATE_LATEX         = NO\r
+\r
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. \r
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be \r
+# put in front of it. If left blank `latex' will be used as the default path.\r
+\r
+LATEX_OUTPUT           = latex\r
+\r
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be \r
+# invoked. If left blank `latex' will be used as the default command name.\r
+\r
+LATEX_CMD_NAME         = latex\r
+\r
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to \r
+# generate index for LaTeX. If left blank `makeindex' will be used as the \r
+# default command name.\r
+\r
+MAKEINDEX_CMD_NAME     = makeindex\r
+\r
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact \r
+# LaTeX documents. This may be useful for small projects and may help to \r
+# save some trees in general.\r
+\r
+COMPACT_LATEX          = NO\r
+\r
+# The PAPER_TYPE tag can be used to set the paper type that is used \r
+# by the printer. Possible values are: a4, a4wide, letter, legal and \r
+# executive. If left blank a4wide will be used.\r
+\r
+PAPER_TYPE             = a4wide\r
+\r
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX \r
+# packages that should be included in the LaTeX output.\r
+\r
+EXTRA_PACKAGES         = \r
+\r
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for \r
+# the generated latex document. The header should contain everything until \r
+# the first chapter. If it is left blank doxygen will generate a \r
+# standard header. Notice: only use this tag if you know what you are doing!\r
+\r
+LATEX_HEADER           = \r
+\r
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated \r
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will \r
+# contain links (just like the HTML output) instead of page references \r
+# This makes the output suitable for online browsing using a pdf viewer.\r
+\r
+PDF_HYPERLINKS         = NO\r
+\r
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of \r
+# plain latex in the generated Makefile. Set this option to YES to get a \r
+# higher quality PDF documentation.\r
+\r
+USE_PDFLATEX           = NO\r
+\r
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. \r
+# command to the generated LaTeX files. This will instruct LaTeX to keep \r
+# running if errors occur, instead of asking the user for help. \r
+# This option is also used when generating formulas in HTML.\r
+\r
+LATEX_BATCHMODE        = NO\r
+\r
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not \r
+# include the index chapters (such as File Index, Compound Index, etc.) \r
+# in the output.\r
+\r
+LATEX_HIDE_INDICES     = NO\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the RTF output\r
+#---------------------------------------------------------------------------\r
+\r
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output \r
+# The RTF output is optimized for Word 97 and may not look very pretty with \r
+# other RTF readers or editors.\r
+\r
+GENERATE_RTF           = NO\r
+\r
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. \r
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be \r
+# put in front of it. If left blank `rtf' will be used as the default path.\r
+\r
+RTF_OUTPUT             = rtf\r
+\r
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact \r
+# RTF documents. This may be useful for small projects and may help to \r
+# save some trees in general.\r
+\r
+COMPACT_RTF            = NO\r
+\r
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated \r
+# will contain hyperlink fields. The RTF file will \r
+# contain links (just like the HTML output) instead of page references. \r
+# This makes the output suitable for online browsing using WORD or other \r
+# programs which support those fields. \r
+# Note: wordpad (write) and others do not support links.\r
+\r
+RTF_HYPERLINKS         = NO\r
+\r
+# Load stylesheet definitions from file. Syntax is similar to doxygen's \r
+# config file, i.e. a series of assignments. You only have to provide \r
+# replacements, missing definitions are set to their default value.\r
+\r
+RTF_STYLESHEET_FILE    = \r
+\r
+# Set optional variables used in the generation of an rtf document. \r
+# Syntax is similar to doxygen's config file.\r
+\r
+RTF_EXTENSIONS_FILE    = \r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the man page output\r
+#---------------------------------------------------------------------------\r
+\r
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will \r
+# generate man pages\r
+\r
+GENERATE_MAN           = NO\r
+\r
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. \r
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be \r
+# put in front of it. If left blank `man' will be used as the default path.\r
+\r
+MAN_OUTPUT             = man\r
+\r
+# The MAN_EXTENSION tag determines the extension that is added to \r
+# the generated man pages (default is the subroutine's section .3)\r
+\r
+MAN_EXTENSION          = .3\r
+\r
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, \r
+# then it will generate one additional man file for each entity \r
+# documented in the real man page(s). These additional files \r
+# only source the real man page, but without them the man command \r
+# would be unable to find the correct page. The default is NO.\r
+\r
+MAN_LINKS              = NO\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the XML output\r
+#---------------------------------------------------------------------------\r
+\r
+# If the GENERATE_XML tag is set to YES Doxygen will \r
+# generate an XML file that captures the structure of \r
+# the code including all documentation.\r
+\r
+GENERATE_XML           = NO\r
+\r
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. \r
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be \r
+# put in front of it. If left blank `xml' will be used as the default path.\r
+\r
+XML_OUTPUT             = xml\r
+\r
+# The XML_SCHEMA tag can be used to specify an XML schema, \r
+# which can be used by a validating XML parser to check the \r
+# syntax of the XML files.\r
+\r
+XML_SCHEMA             = \r
+\r
+# The XML_DTD tag can be used to specify an XML DTD, \r
+# which can be used by a validating XML parser to check the \r
+# syntax of the XML files.\r
+\r
+XML_DTD                = \r
+\r
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will \r
+# dump the program listings (including syntax highlighting \r
+# and cross-referencing information) to the XML output. Note that \r
+# enabling this will significantly increase the size of the XML output.\r
+\r
+XML_PROGRAMLISTING     = YES\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options for the AutoGen Definitions output\r
+#---------------------------------------------------------------------------\r
+\r
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will \r
+# generate an AutoGen Definitions (see autogen.sf.net) file \r
+# that captures the structure of the code including all \r
+# documentation. Note that this feature is still experimental \r
+# and incomplete at the moment.\r
+\r
+GENERATE_AUTOGEN_DEF   = NO\r
+\r
+#---------------------------------------------------------------------------\r
+# configuration options related to the Perl module output\r
+#---------------------------------------------------------------------------\r
+\r
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will \r
+# generate a Perl module file that captures the structure of \r
+# the code including all documentation. Note that this \r
+# feature is still experimental and incomplete at the \r
+# moment.\r
+\r
+GENERATE_PERLMOD       = NO\r
+\r
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate \r
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able \r
+# to generate PDF and DVI output from the Perl module output.\r
+\r
+PERLMOD_LATEX          = NO\r
+\r
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be \r
+# nicely formatted so it can be parsed by a human reader.  This is useful \r
+# if you want to understand what is going on.  On the other hand, if this \r
+# tag is set to NO the size of the Perl module output will be much smaller \r
+# and Perl will parse it just the same.\r
+\r
+PERLMOD_PRETTY         = YES\r
+\r
+# The names of the make variables in the generated doxyrules.make file \r
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. \r
+# This is useful so different doxyrules.make files included by the same \r
+# Makefile don't overwrite each other's variables.\r
+\r
+PERLMOD_MAKEVAR_PREFIX = \r
+\r
+#---------------------------------------------------------------------------\r
+# Configuration options related to the preprocessor   \r
+#---------------------------------------------------------------------------\r
+\r
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will \r
+# evaluate all C-preprocessor directives found in the sources and include \r
+# files.\r
+\r
+ENABLE_PREPROCESSING   = YES\r
+\r
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro \r
+# names in the source code. If set to NO (the default) only conditional \r
+# compilation will be performed. Macro expansion can be done in a controlled \r
+# way by setting EXPAND_ONLY_PREDEF to YES.\r
+\r
+MACRO_EXPANSION        = NO\r
+\r
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES \r
+# then the macro expansion is limited to the macros specified with the \r
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.\r
+\r
+EXPAND_ONLY_PREDEF     = NO\r
+\r
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files \r
+# in the INCLUDE_PATH (see below) will be search if a #include is found.\r
+\r
+SEARCH_INCLUDES        = YES\r
+\r
+# The INCLUDE_PATH tag can be used to specify one or more directories that \r
+# contain include files that are not input files but should be processed by \r
+# the preprocessor.\r
+\r
+INCLUDE_PATH           = \r
+\r
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard \r
+# patterns (like *.h and *.hpp) to filter out the header-files in the \r
+# directories. If left blank, the patterns specified with FILE_PATTERNS will \r
+# be used.\r
+\r
+INCLUDE_FILE_PATTERNS  = \r
+\r
+# The PREDEFINED tag can be used to specify one or more macro names that \r
+# are defined before the preprocessor is started (similar to the -D option of \r
+# gcc). The argument of the tag is a list of macros of the form: name \r
+# or name=definition (no spaces). If the definition and the = are \r
+# omitted =1 is assumed.\r
+\r
+PREDEFINED             = \r
+\r
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then \r
+# this tag can be used to specify a list of macro names that should be expanded. \r
+# The macro definition that is found in the sources will be used. \r
+# Use the PREDEFINED tag if you want to use a different macro definition.\r
+\r
+EXPAND_AS_DEFINED      = \r
+\r
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then \r
+# doxygen's preprocessor will remove all function-like macros that are alone \r
+# on a line, have an all uppercase name, and do not end with a semicolon. Such \r
+# function macros are typically used for boiler-plate code, and will confuse the \r
+# parser if not removed.\r
+\r
+SKIP_FUNCTION_MACROS   = YES\r
+\r
+#---------------------------------------------------------------------------\r
+# Configuration::additions related to external references   \r
+#---------------------------------------------------------------------------\r
+\r
+# The TAGFILES option can be used to specify one or more tagfiles. \r
+# Optionally an initial location of the external documentation \r
+# can be added for each tagfile. The format of a tag file without \r
+# this location is as follows: \r
+#   TAGFILES = file1 file2 ... \r
+# Adding location for the tag files is done as follows: \r
+#   TAGFILES = file1=loc1 "file2 = loc2" ... \r
+# where "loc1" and "loc2" can be relative or absolute paths or \r
+# URLs. If a location is present for each tag, the installdox tool \r
+# does not have to be run to correct the links.\r
+# Note that each tag file must have a unique name\r
+# (where the name does NOT include the path)\r
+# If a tag file is not located in the directory in which doxygen \r
+# is run, you must also specify the path to the tagfile here.\r
+\r
+TAGFILES               = \r
+\r
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create \r
+# a tag file that is based on the input files it reads.\r
+\r
+GENERATE_TAGFILE       = \r
+\r
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed \r
+# in the class index. If set to NO only the inherited external classes \r
+# will be listed.\r
+\r
+ALLEXTERNALS           = NO\r
+\r
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed \r
+# in the modules index. If set to NO, only the current project's groups will \r
+# be listed.\r
+\r
+EXTERNAL_GROUPS        = YES\r
+\r
+# The PERL_PATH should be the absolute path and name of the perl script \r
+# interpreter (i.e. the result of `which perl').\r
+\r
+PERL_PATH              = /usr/bin/perl\r
+\r
+#---------------------------------------------------------------------------\r
+# Configuration options related to the dot tool   \r
+#---------------------------------------------------------------------------\r
+\r
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will \r
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or \r
+# super classes. Setting the tag to NO turns the diagrams off. Note that this \r
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is \r
+# recommended to install and use dot, since it yields more powerful graphs.\r
+\r
+CLASS_DIAGRAMS         = YES\r
+\r
+# If set to YES, the inheritance and collaboration graphs will hide \r
+# inheritance and usage relations if the target is undocumented \r
+# or is not a class.\r
+\r
+HIDE_UNDOC_RELATIONS   = YES\r
+\r
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is \r
+# available from the path. This tool is part of Graphviz, a graph visualization \r
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section \r
+# have no effect if this option is set to NO (the default)\r
+\r
+HAVE_DOT               = NO\r
+\r
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen \r
+# will generate a graph for each documented class showing the direct and \r
+# indirect inheritance relations. Setting this tag to YES will force the \r
+# the CLASS_DIAGRAMS tag to NO.\r
+\r
+CLASS_GRAPH            = YES\r
+\r
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen \r
+# will generate a graph for each documented class showing the direct and \r
+# indirect implementation dependencies (inheritance, containment, and \r
+# class references variables) of the class with other documented classes.\r
+\r
+COLLABORATION_GRAPH    = YES\r
+\r
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and \r
+# collaboration diagrams in a style similar to the OMG's Unified Modeling \r
+# Language.\r
+\r
+UML_LOOK               = NO\r
+\r
+# If set to YES, the inheritance and collaboration graphs will show the \r
+# relations between templates and their instances.\r
+\r
+TEMPLATE_RELATIONS     = NO\r
+\r
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT \r
+# tags are set to YES then doxygen will generate a graph for each documented \r
+# file showing the direct and indirect include dependencies of the file with \r
+# other documented files.\r
+\r
+INCLUDE_GRAPH          = YES\r
+\r
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and \r
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each \r
+# documented header file showing the documented files that directly or \r
+# indirectly include this file.\r
+\r
+INCLUDED_BY_GRAPH      = YES\r
+\r
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will \r
+# generate a call dependency graph for every global function or class method. \r
+# Note that enabling this option will significantly increase the time of a run. \r
+# So in most cases it will be better to enable call graphs for selected \r
+# functions only using the \callgraph command.\r
+\r
+CALL_GRAPH             = NO\r
+\r
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen \r
+# will graphical hierarchy of all classes instead of a textual one.\r
+\r
+GRAPHICAL_HIERARCHY    = YES\r
+\r
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images \r
+# generated by dot. Possible values are png, jpg, or gif\r
+# If left blank png will be used.\r
+\r
+DOT_IMAGE_FORMAT       = png\r
+\r
+# The tag DOT_PATH can be used to specify the path where the dot tool can be \r
+# found. If left blank, it is assumed the dot tool can be found on the path.\r
+\r
+DOT_PATH               = \r
+\r
+# The DOTFILE_DIRS tag can be used to specify one or more directories that \r
+# contain dot files that are included in the documentation (see the \r
+# \dotfile command).\r
+\r
+DOTFILE_DIRS           = \r
+\r
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width \r
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than \r
+# this value, doxygen will try to truncate the graph, so that it fits within \r
+# the specified constraint. Beware that most browsers cannot cope with very \r
+# large images.\r
+\r
+MAX_DOT_GRAPH_WIDTH    = 1024\r
+\r
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height \r
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than \r
+# this value, doxygen will try to truncate the graph, so that it fits within \r
+# the specified constraint. Beware that most browsers cannot cope with very \r
+# large images.\r
+\r
+MAX_DOT_GRAPH_HEIGHT   = 1024\r
+\r
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the \r
+# graphs generated by dot. A depth value of 3 means that only nodes reachable \r
+# from the root by following a path via at most 3 edges will be shown. Nodes that \r
+# lay further from the root node will be omitted. Note that setting this option to \r
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also \r
+# note that a graph may be further truncated if the graph's image dimensions are \r
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). \r
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.\r
+\r
+MAX_DOT_GRAPH_DEPTH    = 0\r
+\r
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will \r
+# generate a legend page explaining the meaning of the various boxes and \r
+# arrows in the dot generated graphs.\r
+\r
+GENERATE_LEGEND        = YES\r
+\r
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will \r
+# remove the intermediate dot files that are used to generate \r
+# the various graphs.\r
+\r
+DOT_CLEANUP            = YES\r
+\r
+#---------------------------------------------------------------------------\r
+# Configuration::additions related to the search engine   \r
+#---------------------------------------------------------------------------\r
+\r
+# The SEARCHENGINE tag specifies whether or not a search engine should be \r
+# used. If set to NO the values of all tags below this one will be ignored.\r
+\r
+SEARCHENGINE           = NO\r
diff --git a/bertos/net/nmeap/Makefile b/bertos/net/nmeap/Makefile
new file mode 100644 (file)
index 0000000..425079a
--- /dev/null
@@ -0,0 +1,23 @@
+# rules
+export CC=gcc
+export CDEFS = -DNDEBUG
+
+# directories
+BASE :=$(shell pwd)
+export SRC=$(BASE)/src
+export TST=$(BASE)/tst
+export INC=$(BASE)/inc
+export LIB=$(BASE)/lib
+
+all :
+       cd $(SRC) && $(MAKE) all
+       cd $(TST) && $(MAKE) all
+       
+
+clean :
+       cd $(SRC) && $(MAKE) clean
+       cd $(TST) && $(MAKE) clean
+       
+doc  :
+       doxygen
+
diff --git a/bertos/net/nmeap/README b/bertos/net/nmeap/README
new file mode 100644 (file)
index 0000000..bc2a6a0
--- /dev/null
@@ -0,0 +1,24 @@
+NMEAP is licensed under the BSD Open Source License. See the file COPYING for terms of the license
+
+VERSION 0.2 - bug fixes and tutorial
+       a. fixed a bug in test3.c
+       b. added a tutorial in doc/tutorial.html
+
+Installation:
+
+Unpack the tarball or zip file into the desired working directory.
+
+Building:
+
+Under Linux, execute 'make' from the top level directory.
+
+Under Win32, execute 'nmake -f win32.mak' from the top level directory
+
+Using:
+
+This library is statically linked to the application. Just include it in 
+your linker command line. See the file 'nmeap.h' and the examples in the
+'tst' directory for usage instructions.
+
+
+
diff --git a/bertos/net/nmeap/doc/tutorial.html b/bertos/net/nmeap/doc/tutorial.html
new file mode 100644 (file)
index 0000000..539a05a
--- /dev/null
@@ -0,0 +1,151 @@
+<html>\r
+<body>\r
+<h1>NMEAP TUTORIAL AND REFERENCE</h1>\r
+<hr />\r
+<pre>\r
+copyright (c) 2005 David M. Howard\r
+This work is licensed under the Creative Commons Attribution License.\r
+To view a copy of this license, visit\r
+http://creativecommons.org/licenses/by/2.0/ or send a letter to\r
+Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305,USA\r
+You are free:\r
+    * to copy, distribute, display, and perform the work\r
+    * to make derivative works\r
+    * to make commercial use of the work\r
+Under the following conditions:\r
+Attribution. You must give the original author credit.\r
+    * For any reuse or distribution, you must make clear to others the\r
+      license terms of this work.\r
+    * Any of these conditions can be waived if you get permission from\r
+      the author.\r
+</pre>  \r
+<hr />\r
+<h2>Table Of Contents</h2>\r
+<ol>\r
+<li><a href="#c1">Installing the Source Code</a></li>\r
+<li><a href="#c2">Building the Library</a></li>\r
+<li><a href="#c3">Description and Examples</a></li>\r
+<li><a href="#c4">API Documentation</a></li>\r
+</ol>\r
+<a name="c1">&nbsp;</a>\r
+</a><h2>1. Installing the source code</h2>\r
+Get the source code from <a href="http://sourceforge.net/projects/nmeap/">NMEAP at sourceforge.net</a>\r
+<pre>\r
+\r
+Linux:\r
+       expand the tarball to a directory of your choice.\r
+       >tar --gzip -xf [tarball name]\r
+       >cd [nmeap...]\r
+       \r
+Windows:\r
+       use Winzip to unzip the zipfile to a directory of your choice\r
+       \r
+</pre>\r
+\r
+<a name="c2">&nbsp;</a>\r
+<h2>2. Building the library </h2>\r
+<pre>\r
+\r
+Linux:\r
+       >cd [working directory]\r
+       >make\r
+       This builds a static library named libnmeap.a in the 'lib' directory. there is no option for a dynamic library. \r
+       This thing is so small that it isn't worth the trouble. It also builds the test/examples programs in\r
+       'tst'.\r
+       \r
+Windows:\r
+       >cd [working directory]\r
+       >nmake -f win32.mak\r
+       Again, this builds a static library names libnmeap.lib in the 'lib' direcotry, plus the test programs in 'tst'\r
+</pre>\r
+<a name="c3">&nbsp;</a>\r
+<h2>3. Description and Examples</h2>\r
+<p>The NMEA-0183 standard specifies how the output is formatted for GPS data output, usually on a serial port. The data \r
+consists of 'sentences' delimited by CR/LF end of line markers. A lot has been written about the format, so this document\r
+won't cover the specifics. A good place to start is the <a href="http://vancouver-webpages.com/peter/nmeafaq.txt">NMEA FAQ</a> \r
+maintained by Peter Bennett.</p> \r
+<p>NMEAP is an extensible C language parser library that takes NMEA sentences as input and spits out the decoded data as output. You link\r
+NMEAP in to your application, set it up, initialize it and feed it bytes. It signals you when it has found a complete valid sentence and \r
+provides the parsed out data to you. Parsing NMEA-0183 is pretty easy but it has a few tricky bits. The value of NMEAP is not that it is\r
+rocket science to write an NMEA parser, but that it provides a relatively efficient implementation that works, along with an\r
+extension framework to add more sentence parsers without hacking the base source code.</p>\r
+<p>An NMEA 'sentence' has the following format:</p>\r
+<pre>\r
+       $name,data1,data2,...,dataN*XX[CR/LF]\r
+       OR\r
+       $name,data1,data2,...,dataN[CR/LF]\r
+       \r
+where\r
+       header       := a 5 digit sentence identifier. all ASCII upper case. e.g. GPGGA\r
+       data1..dataN := some number of data elements, all ASCII numbers or letters, in all kinds of weird formats.\r
+                    fields can be empty, in which case 2 commas will be side by side.\r
+                    normally data fields are identified by their position in the sentence. \r
+       *XX          := a '*' plus two ASCII hex digits of checksum. this field is optional.\r
+       [CR/LF]      := end of line is terminated by a carriage return/linefeed pair.\r
+       \r
+example from the <a href="http://vancouver-webpages.com/peter/nmeafaq.txt">NMEA FAQ</a>:\r
+       $GPGGA,123519,4807.038,N,01131.324,E,1,08,0.9,545.4,M,46.9,M,,*42\r
+</pre> \r
+<p>The NMEAP parser works as follows:\r
+<ol>\r
+       <li>the application sets up the parser and specifies which sentences are to be parsed\r
+               and what is to be done with the output data from the parser.</li>\r
+       <li>the application reads raw bytes from its IO device and passes the bytes to the parser,\r
+               either byte by byte or as a buffer/length pair.</li>\r
+       <li>nmeap:\r
+       <ul>\r
+               <li>runs the input bytes through a lexical scanner that recognizes complete and valid sentences</li>\r
+               <li>when a sentence is recognized, a second lexical scanner divides the sentence into discrete tokens.</li>\r
+               <li>the name field is matched internally to a sentence parser for that name</li>\r
+               <li> the sentence parser picks out the data strings and decodes them into an nmeap or user \r
+               defined data structure  with normal data types such as integer, float, double etc. </li>\r
+               <li>notifies the client application that a sentence was found and decoded, either thru a callout \r
+               to an event handler (ala Expat) or via a return code and a shared data structure, or both.</li>\r
+       </ul>\r
+       </li>\r
+</ol>\r
+<h4>Sentence Parsers</h4>\r
+<p>Most of the work in NMEAP is done by the sentence parsers. Each type of NMEA sentence string has an associated parser. NMEAP provides\r
+standard ones, and the user can add more in a systematic way.\r
+The sentence parser is responsible for knowing the token position of the data elements and whatever format they \r
+are in. There are functions in nmeap to decode standard data element formats. If something is nonstandard, \r
+the sentence parser decodes it. Each sentence parser has a 'struct' type associated with it\r
+that the decoded data gets poked into an instance of that data structure, which is provided by the client application when nmeap is set\r
+up.</p>\r
+<h4>Memory Allocation</h4>\r
+<p>All memory allocation is done by the application. Several data items are required. The application can declare them statically or use\r
+malloc or whatever. NMEAP doesn't do any memory allocation on its own. This is an important requirement for portability and especially in\r
+embedded systems where memory allocation needs to be tightly defined and controlled.\r
+</p>\r
+<h4>Threads</h4>\r
+<p>NMEAP as implemented is not meant to be called from multiple threads. It expects to execute within the context of a single thread. The sentence callouts execute\r
+in the context of the thread of the nmeap client thread. Given how nmeap works, it doesn't really make sense to make nmeap thread-safe\r
+because the usage pattern is intrinsically single thread. If one wanted to, one could add some mutex locking within the nmeap function\r
+calls to make it thread safe. In a multithreaded environment, a more likely approach to thread-safety is to put synchronization in the client side of the application,\r
+within the sentence parser callouts or inline handling of sentence data.\r
+</p>\r
+<h4>IO</h4>\r
+<p>NMEAP is IO agnostic. That is a pompous way of saying that NMEAP doesn't do the IO, the client application does it. There are way too\r
+many IO schemes to handle to keep it portable, especially in the embedded world. That said, the example programs contain a Linux and a Win32 specific\r
+program that includes serial IO for those two platforms.\r
+</p>\r
+\r
+<h4>Examples</h4>\r
+Look at the code for the following example programs to see the usage patterns. The are all located in the\r
+'tst' directory. There are big, obvious comments delineating the steps to setting up and using NMEAP.\r
+The IO is simulated in the samples. Follow the comments in the code\r
+to see the sequence of operations to setup and run the parser. When you are ready just plug in your own IO.\r
+<ol>\r
+       <li>tst/test1.c Setup for standard GGA and RMC sentences with byte by byte IO (easiest to code up)</li>\r
+       <li>tst/test2.c Setup for standard GGA and RMC sentences with block IO (more efficient from a system call standpoint)</li>\r
+       <li>tst/test3.c Adding a custom parser</li>\r
+       <li>tst/wingps.c A console program that reads a serial port and writes the decoded data to standard out for WIN32 applications</li>\r
+</ol>\r
+<a name="c4">&nbsp;</a>\r
+<h3>API Documentation</h3>\r
+The documentation for the actual API is in <a href="www.doxygen.org">Doxygen<a> HTML format and is contained in the 'doc' directory of\r
+the source distribution. Or, all the external data structures, constants and functions are defined in 'inc/nmeap.h'. \r
+\r
+<p>END</p>\r
+</body>\r
+</html>\r
diff --git a/bertos/net/nmeap/inc/nmeap.h b/bertos/net/nmeap/inc/nmeap.h
new file mode 100644 (file)
index 0000000..6386c66
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License.
+see the file COPYING for more details.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+#ifndef __NMEAP_H__
+#define __NMEAP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 
+============================================
+COMPILE TIME CONFIGURATION CONSTANTS
+============================================
+*/
+
+/* these constants affect the size of the context object. tweak them as desired but know what you are doing */
+
+/** maximum number of sentence parsers supported */
+#define NMEAP_MAX_SENTENCES            8
+/** length of sentence name. leave this at 5 unless you really know what you are doing */
+#define NMEAP_MAX_SENTENCE_NAME_LENGTH 5
+/** max length of a complete sentence. the standard says 82 bytes, but its probably better to go at least 128 since
+ * some units don't adhere to the 82 bytes especially for proprietary sentences */
+#define NMEAP_MAX_SENTENCE_LENGTH      255
+/** max tokens in one sentence. 24 is enough for any standard sentence */
+#define NMEAP_MAX_TOKENS               24
+
+/* predefined message ID's */
+
+/* GGA MESSAGE ID */
+#define NMEAP_GPGGA 1
+/* RMC MESSAGE ID */
+#define NMEAP_GPRMC 2
+
+/** user defined parsers should make ID numbers using NMEAP_USER as the base value, plus some increment */
+#define NMEAP_USER  100
+
+/* forward references */
+struct nmeap_context;
+struct nmeap_sentence;
+
+/* 
+============================================
+CALLOUTS
+============================================
+*/
+
+/**
+ * sentence callout function type
+ * a callout is fired for each registered sentence type
+ * the callout gets the object context and a pointer to sentence specific data.
+ * the callout must cast the 'sentence_data' to the appropriate type for that callout
+ * @param context                      nmea object context
+ * @param sentence_data                sentence specific data
+*/ 
+typedef void (*nmeap_callout_t)(struct nmeap_context *context,void *sentence_data,void *user_data);
+
+/**
+ * sentence parser function type
+ * stored in the object context and called internally when the sentence name matches
+ * the specified value
+ * the callout gets the object context and a pointer to sentence specific data.
+ * the callout must cast the 'sentence_data' to the appropriate type for that callout
+ * @param context                      nmea object context
+ * @param sentence_data                sentence specific data
+ * @return id of sentence  (each sentence parser knows its own ID)
+*/ 
+typedef int (*nmeap_sentence_parser_t)(struct nmeap_context *context,struct nmeap_sentence *sentence);
+
+
+/* ==== opaque types === */
+#include "nmeap_def.h"
+
+
+/* 
+============================================
+STANDARD SENTENCE DATA STRUCTURES
+============================================
+*/
+
+/** extracted data from a GGA message */
+struct nmeap_gga {
+       double        latitude;
+       double        longitude;
+       double        altitude;
+       unsigned long time;
+       int           satellites;
+       int           quality;
+       double        hdop;
+       double        geoid;
+};
+typedef struct nmeap_gga nmeap_gga_t;
+
+/** extracted data from an RMC message */
+struct nmeap_rmc {
+       unsigned long time;
+       char          warn;
+       double        latitude;
+       double        longitude;
+       double        speed;
+       double        course;
+       unsigned long date;
+       double        magvar;
+};
+
+typedef struct nmeap_rmc nmeap_rmc_t;
+
+/* 
+============================================
+METHODS
+============================================
+*/
+
+/**
+ * initialize an NMEA parser. call this function to initialize a user allocated context object
+ * @param context              nmea object context. allocated by user statically or dynamically.
+ * @param user_data    pointer to user defined data
+ * @return 0 if ok, -1 if initialization failed
+ */
+int nmeap_init(nmeap_context_t *context,void *user_data);
+
+/**
+ * register an NMEA sentence parser
+ * @param context                 nmea object context
+ * @param sentence_name    string matching the sentence name for this parser. e.g. "GPGGA". not including the '$'
+ * @param sentence_parser  parser function for this sentence
+ * @param sentence_callout callout triggered when this sentence is received and parsed. 
+ *                         if null, no callout is triggered for this sentence
+ * @param sentence_data    user allocated sentence specific data defined by the application. the parser uses
+                           this data item to store the extracted data. This data object needs to persist over the life
+                                                  of the parser, so be careful if allocated on the stack. 
+ * @return 0 if registered ok, -1 if registration failed
+ */
+int nmeap_addParser(nmeap_context_t         *context,
+                                        const char             *sentence_name,
+                                        nmeap_sentence_parser_t sentence_parser,
+                                        nmeap_callout_t         sentence_callout,
+                                        void                   *sentence_data
+                                        );
+
+/** 
+ * parse a buffer of nmea data.
+ * @param context                 nmea object context
+ * @param buffer          buffer of input characters
+ * @param length          [in,out] pointer to length of buffer. on return, contains number of characters not used for
+ *                        the current sentence
+ * @return -1 if error, 0 if the data did not complete a sentence, sentence code if a sentence was found in the stream
+ */
+int nmeap_parseBuffer(nmeap_context_t *context,const char *buffer,int *length);
+
+/** 
+ * parse one character of nmea data.
+ * @param context                 nmea object context
+ * @param ch              input character
+ * @return -1 if error, 0 if the data did not complete a sentence, sentence code if a sentence was found in the stream  
+ */
+int nmeap_parse(nmeap_context_t *context,char ch);
+
+
+/** 
+ * built-in parser for GGA sentences.
+ * @param context                 nmea object context
+ * @param sentence         sentence object for this parser
+  */
+int nmeap_gpgga(nmeap_context_t *context,nmeap_sentence_t *sentence);
+
+/** 
+ * built-in parser for RMC sentences.
+ * @param context                 nmea object context
+ * @param sentence         sentence object for this parser
+ */
+int nmeap_gprmc(nmeap_context_t *context,nmeap_sentence_t *sentence);
+
+/**
+ * extract latitude from 2 tokens in ddmm.mmmm,h format.
+ * @param plat pointer to token with numerical latitude
+ * @param phem pointer to token with hemisphere
+ * @return latitude in degrees and fractional degrees
+ */
+double nmeap_latitude(const char *plat,const char *phem);
+
+
+/**
+ * extract longitude from 2 tokens in ddmm.mmmm,h format.
+ * @param plat pointer to token with numerical longitude
+ * @param phem pointer to token with hemisphere
+ * @return longitude in degrees and fractional degrees
+ */
+double nmeap_longitude(const char *plat,const char *phem);
+
+#ifdef __cplusplus
+} // extern C
+#endif
+
+
+#endif
+
diff --git a/bertos/net/nmeap/inc/nmeap_def.h b/bertos/net/nmeap/inc/nmeap_def.h
new file mode 100644 (file)
index 0000000..c9d1a3c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License.
+see the file COPYING for more details.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+#ifndef __NMEAP_DEF_H__
+#define __NMEAP_DEF_H__
+
+/**
+ * context for a single sentence 
+ */
+typedef struct nmeap_sentence {
+    char                    name[NMEAP_MAX_SENTENCE_NAME_LENGTH + 1];
+       int                     id;
+    nmeap_sentence_parser_t parser;
+    nmeap_callout_t         callout;
+    void                   *data;
+} nmeap_sentence_t;
+
+/** 
+ * parser context
+ */
+struct nmeap_context {
+       /** support up to 8 sentences */
+       nmeap_sentence_t sentence[NMEAP_MAX_SENTENCES];         /* sentence descriptors */
+       int              sentence_count;                                                /* number of initialized descriptors */
+       
+       /** sentence input buffer */
+       char             input[NMEAP_MAX_SENTENCE_LENGTH + 1];   /* input line buffer */
+       int              input_count;                           /* index into 'input */
+       int              input_state;                           /* current lexical scanner state */
+       char             input_name[6];                        /* sentence name */
+       char             icks;                                          /* input checksum    */
+       char             ccks;                                          /* computed checksum */
+       
+       /* tokenization */
+       char            *token[NMEAP_MAX_TOKENS];              /* list of delimited tokens */
+       int              tokens;                                                             /* list of tokens */
+       
+       /** errors and debug. optimize these as desired */
+       unsigned long    msgs;    /* count of good messages */
+       unsigned long    err_hdr; /* header error */                                                    
+       unsigned long    err_ovr; /* overrun error */
+       unsigned long    err_unk; /* unknown error */
+       unsigned long    err_id;  /* bad character in id */
+       unsigned long    err_cks; /* bad checksum */
+       unsigned long    err_crl; /* expecting cr or lf, got something else */
+       char             debug_input[NMEAP_MAX_SENTENCE_LENGTH + 1];     /* input line buffer for debug */
+       
+       /** opaque user data */
+       void *user_data;
+};
+
+typedef struct nmeap_context nmeap_context_t;
+
+#endif /* __NMEAP_DEF_H__ */ 
diff --git a/bertos/net/nmeap/src/Makefile b/bertos/net/nmeap/src/Makefile
new file mode 100644 (file)
index 0000000..5e94960
--- /dev/null
@@ -0,0 +1,31 @@
+# specify compiler flags
+CFLAGS = -I $(INC) $(CDEFS) -g -O0 -Werror -Wall
+
+# set library name
+LIBNAME  = libnmeap.a
+
+COBJ     = nmeap01.o
+
+INCLUDES=      $(INC)/nmeap.h $(INC)/nmeap_def.h
+
+# build everything
+all : $(LIB)/$(LIBNAME)
+
+# build the library
+$(LIB)/$(LIBNAME) : $(COBJ)
+       -$(RM) $(LIB)/$(LIBNAME)
+       $(AR)  -q $(LIB)/$(LIBNAME) $(COBJ)
+
+# build all c files into .o files
+$(COBJ): %.o: %.c
+       $(CC) -c $(CFLAGS) $(SRC)/$< -o $@      
+
+# erase all intermediate and output files
+clean :
+       -$(RM) *.o
+       -$(RM) *~
+       -$(RM) $(LIB)/$(LIBNAME)
+
+# include file dependencies
+$(COBJ) : $(INCLUDES)
+
diff --git a/bertos/net/nmeap/src/nmeap.mak b/bertos/net/nmeap/src/nmeap.mak
new file mode 100644 (file)
index 0000000..703ffc9
--- /dev/null
@@ -0,0 +1,20 @@
+INCLUDES= ..\inc\nmeap.h ..\inc\nmeap_def.h\r
+CSRC    = nmeap01.c\r
+LIBNAME = ..\lib\libnmeap.lib\r
+\r
+# build everything\r
+all : $(LIBNAME)\r
+\r
+$(LIBNAME) : nmeap01.obj\r
+       -erase $(LIBNAME)\r
+       lib /OUT:$(LIBNAME) nmeap01.obj\r
+\r
+nmeap01.obj : nmeap01.c $(INCLUDES)\r
+       cl /DNDEBUG /c /I..\inc nmeap01.c\r
+\r
+# erase all intermediate and output files\r
+clean :\r
+       -erase *.obj\r
+       -erase $(LIBNAME)\r
+\r
+\r
diff --git a/bertos/net/nmeap/src/nmeap01.c b/bertos/net/nmeap/src/nmeap01.c
new file mode 100644 (file)
index 0000000..82b041e
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License.
+see the file COPYING for more details.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+/**
+ * nmeap01.c
+ * nmeap gps data parser
+ * 
+ * see the file COPYING for terms of the licnese
+*/ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "nmeap.h"
+
+/* this only works if you are sure you have an upper case hex digit */
+#define HEXTOBIN(ch) ((ch <= '9') ? ch - '0' : ch - ('A' - 10))
+
+/* forward references */
+int nmeap_init(nmeap_context_t *context,void *user_data);
+int nmeap_addParser(nmeap_context_t         *context,
+                                        const char             *sentence_name,
+                                        nmeap_sentence_parser_t sentence_parser,
+                                        nmeap_callout_t         sentence_callout,
+                     void                  *sentence_data
+                                        );
+int nmeap_tokenize(nmeap_context_t *context);
+int nmeap_process(nmeap_context_t *context);
+int nmeap_parse(nmeap_context_t *context,char ch);
+int nmeap_parseBuffer(nmeap_context_t *context,const char *buffer,int *length);
+
+/**
+ * get a latitude out of a pair of nmea tokens 
+ */
+double nmeap_latitude(const char *plat,const char *phem)
+{
+    double lat;
+    int    deg;
+    double min;
+    int    ns;
+    
+    assert(plat != 0);
+    assert(phem != 0);
+    
+    if (*plat == 0) {
+        return 0.0;
+    }
+    if (*phem == 0) {
+        return 0.0;
+    }
+    
+    /* north lat is +, south lat is - */
+    if (*phem == 'N') {
+        ns = 1;
+    }
+    else {
+        ns = -1;
+    }
+    
+    /* latitude is degrees, minutes, fractional minutes */
+    /* no validation is performed on the token. it better be good.*/
+    /* if it comes back 0.0 then probably the token was bad */
+    lat = atof(plat);
+    
+    /* extract the degree part */
+    deg = (int)(lat / 100.0);
+    
+    /* mask out the degrees */
+    min = lat - (deg * 100.0);
+    
+    /* compute the actual latitude in degrees.decimal-degrees */
+    lat = (deg + (min / 60.0)) * ns;
+    
+    return lat;
+}
+
+/**
+ * get a longitude out of a pair of nmea tokens 
+ */
+double nmeap_longitude(const char *plon,const char *phem)
+{
+    double lon;
+    int    deg;
+    double min;
+    int    ew;
+    
+    assert(plon != 0);
+    assert(phem != 0);
+    
+    if (*plon == 0) {
+        return 0.0;
+    }
+    if (*phem == 0) {
+        return 0.0;
+    }
+    
+    /* west long is negative, east long is positive */
+    if (*phem == 'E') {
+        ew = 1;
+    }
+    else {
+        ew = -1;
+    }
+    
+    /* longitude is degrees, minutes, fractional minutes */
+    /* no validation is performed on the token. it better be good.*/
+    /* if it comes back 0.0 then probably the token was bad */
+    lon = atof(plon);
+    
+    /* extract the degree part */
+    deg = (int)(lon / 100.0);
+    
+    /* mask out the degrees */
+    min = lon - (deg * 100.0);
+    
+    /* compute the actual lonitude in degrees.decimal-degrees */
+    lon = (deg + (min / 60.0)) * ew;
+
+    
+    return lon;
+}
+
+/**
+ * get an altitude longitude out of a pair of nmea tokens
+ * ALTITUDE is returned in METERS 
+ */
+double nmeap_altitude(const char *palt,const char *punits)
+{
+    double alt;
+    
+    if (*palt == 0) {
+        return 0.0;
+    }
+    
+    /* convert with no error checking */
+    alt = atof(palt);
+    
+    if (*punits == 'M') {
+        /* already in meters */ 
+    }
+    else if (*punits == 'F') {
+        /* convert to feet */
+        alt = alt * 3.2808399;
+    }
+    
+    return alt;
+}
+
+/**
+ * initialize an NMEA parser
+ */
+int nmeap_init(nmeap_context_t *context,void *user_data)
+{
+    assert(context != 0);
+
+    memset(context,0,sizeof(*context));
+
+    context->user_data = user_data;
+
+    return 0;    
+}
+
+/**
+ * register an NMEA sentence parser
+ */
+int nmeap_addParser(nmeap_context_t         *context,
+                                        const char             *sentence_name,
+                                        nmeap_sentence_parser_t sentence_parser,
+                                        nmeap_callout_t         sentence_callout,
+                     void                  *sentence_data
+                                        )
+{
+    nmeap_sentence_t *s = 0;
+    
+    /* runtime error */
+    assert(context != 0);
+    
+    /* sentence capacity overflow */
+    if (context->sentence_count >= NMEAP_MAX_SENTENCES) {
+        return -1;
+    }
+    
+    /* point at next empty sentence buffer */
+    s = &context->sentence[context->sentence_count];
+    
+    /* advance sentence data count */
+    context->sentence_count++;
+    
+    /* clear the sentence data */
+    memset(s,0,sizeof(*s));
+    
+    /* name */
+    strncpy(s->name,sentence_name,NMEAP_MAX_SENTENCE_NAME_LENGTH);
+    
+    /* parser */
+    s->parser = sentence_parser;
+    
+    /* callout */
+    s->callout = sentence_callout;
+    
+    /* data */
+    s->data    = sentence_data;
+
+    return 0;
+}
+
+/** 
+ * tokenize a buffer
+ */
+int nmeap_tokenize(nmeap_context_t *context)
+{
+    char *s;
+    int   tokens;
+    int   state;
+    
+    /* first token is header. assume it is there */
+    tokens = 0;
+    s = context->input;
+    context->token[tokens] = s;
+    
+    /* get rest of tokens */
+    tokens = 1;
+    state = 0;
+    while((*s != 0)&&(tokens < NMEAP_MAX_TOKENS)) {
+        switch(state) {
+        case 0:
+            /* looking for end of a token */
+            if (*s == ',') {
+                /* delimit at the comma */
+                *s    = 0;
+                /* new token */
+                state = 1;
+            }
+            break;
+        case 1:
+            /* start of next token, might be another comma */
+            context->token[tokens++] = s;
+            if (*s == ',') {
+                /* delimit at the comma */
+                *s    = 0;
+            }
+            else {   
+                /* not a comma */
+                state = 0;
+            }
+            break;
+        default:
+            state = 0;
+            break;
+        }
+        
+        // next character
+        s++;
+    }
+    return tokens;
+}
+
+/**
+ * process a sentence 
+ */
+int nmeap_process(nmeap_context_t *context)
+{
+    int id;
+    int i;
+    nmeap_sentence_t *s;
+       
+    /* copy the input to a debug buffer */
+    /* remove debug_input when everything is working. */
+    strncpy(context->debug_input,context->input,sizeof(context->debug_input));
+    
+    /* tokenize the input */
+    context->tokens = nmeap_tokenize(context);
+    
+    /* try to find a matching sentence parser */
+    /* this search is O(n). it has a lot of potential for optimization, at the expense of complexity, if you have a lot of sentences */
+    /* binary search instead of linear (have to keep sentences in sorted order) O(NlogN) */
+    /* OR, when sentences are added, create a TRIE structure to find the names with a constant time search O(5) */
+    for(i=0;i<context->sentence_count;i++) {
+        s = &context->sentence[i];
+        assert(s != 0);
+        if (strncmp(context->input_name,s->name,5) == 0) {
+            /* found a match, call its parser */
+            id = (*context->sentence[i].parser)(context,s);
+            if (id > 0) {
+                break;
+            }
+        }
+    }
+        
+    return id;
+}
+
+/**
+                 +-5-+              +---+
+                 v   |              v   |
+ +------+       +------+           +------+         +------+         +------+
+ |   0  |--$--> |1-hdr |--alnum--> |2-data|----\r-->| 6-LF |---\n--->| done |--> 0
+ +------+       +------+           +------+         +------+         +------+
+                                    |                 ^
+                                    *                 +--------\r-------+
+                                    V                                   |
+                                 +------+           +------+         +------+
+                                 |3-cks |--xdigit-->|4-cks |-xdigit->| 5-CR |
+                                 +------+           +------+         +------+
+                                 
+return to start conditions:
+1. buffer overflow
+2. invalid character for state
+
+checksum calculation
+two hex digits represent the XOR of all characters between, but not
+including, the "$" and "*".  A checksum is required on some
+sentences.
+
+*/
+int nmeap_parse(nmeap_context_t *context,char ch)
+{
+    int status = 0;
+    
+    /* check for input buffer overrun first to avoid duplicating code in the
+    individual states
+    */
+    if (context->input_count >= (sizeof(context->input)-1)) {
+        /* input buffer overrun, restart state machine */
+        context->input_state = 0;
+        /* reset input count */
+        context->input_count = 0;
+    }
+    
+    /* store the byte */
+    context->input[context->input_count] = ch;
+    
+    /* next buffer position */
+    context->input_count++;
+    
+    /* run it through the lexical scanner */
+    switch(context->input_state) {
+    /* LOOKING FOR $ */
+    case 0:
+        if (ch == '$') {
+            /*look for id */
+            context->input_state = 1;
+            context->ccks        = 0;
+                       context->icks        = 0;
+        }
+        else {
+            /* header error, start over */
+            context->err_hdr++;
+            context->input_state = 0;
+            context->input_count = 0;
+        }
+        break;
+    /* LOOKING FOR 5 CHARACTER SENTENCE ID */
+    case 1:
+        /* allow numbers even though it isn't usually done */
+        /* a proprietary id might have a numeral */
+        if (isalnum(ch)) {
+            /* store name separately */
+            context->input_name[context->input_count - 2] = ch;
+            /* checksum */
+            context->ccks ^= ch;
+            /* end of header? */
+            if (context->input_count >= 6) {
+                /* yes, get body */
+                context->input_state = 2;
+            }
+        }
+        else {
+            /* bad character, start over */
+            context->err_id++;
+            context->input_state = 0;
+            context->input_count = 0;
+        }
+        break;
+    /* LOOKING FOR CR OR CHECKSUM INDICATOR */
+    case 2:
+        if (ch == '*') {
+            /* this sentence has a checksum */
+            context->input_state = 3;
+        }
+        else if (ch == '\r') {
+            /* carriage return, no checksum, force a match */
+                       context->icks = 0;
+                       context->ccks = 0;
+            context->input_state = 6;
+        }
+        else {
+            /* continue accumulating data */
+            /* checksum */
+            context->ccks ^= ch;
+        }
+        break;
+    /* LOOKING FOR FIRST CHECKSUM CHARACTER */
+    case 3:
+        /* must be upper case hex digit */
+        if (isxdigit(ch) && (ch <= 'F')) {
+            /* got first checksum byte */
+            context->input_state = 4;
+            context->icks = HEXTOBIN(ch) << 4;
+        }
+        else {
+            /* input error, restart */
+            context->err_cks++;
+            context->input_state = 0;
+            context->input_count = 0;
+        }
+        break;
+        /* LOOKING FOR SECOND CHECKSUM CHARACTER */
+    case 4:
+        /* must be upper case hex digit */
+        if (isxdigit(ch) && (ch <= 'F')) {
+            /* got second checksum byte */
+            context->input_state = 5;
+            context->icks += HEXTOBIN(ch);
+        }
+        else {
+            /* input error, restart */
+            context->err_cks++;
+            context->input_state = 0;
+            context->input_count = 0;
+        }
+        break;
+    /* LOOKING FOR CR */
+    case 5:
+        if (ch == '\r') {
+            /* carriage return */
+            context->input_state = 6;
+        }
+        else {
+            /* input error, restart */
+            context->err_crl++;
+            context->input_state = 0;
+            context->input_count = 0;
+        }
+        break;
+    /* LOOKING FOR LINE FEED */
+    case 6:
+        if (ch == '\n') {
+            /* linefeed, line complete */
+            
+            /* delimit buffer */
+            context->input[context->input_count] = 0;
+            
+            /* if the checksums match, process the sentence */
+                       if (context->ccks == context->icks) {
+                               /* process */
+                               status = nmeap_process(context);
+                               
+                               /* count good messages */
+                               context->msgs++;
+                       }
+                       else {
+                               /* count checksum errors */
+                               context->err_cks++;
+                       }
+            
+            /* restart next time */
+            context->input_state = 0;
+            context->input_count = 0;
+        }
+        else {
+            /* input error, restart */
+            context->err_crl++;
+            context->input_state = 0;
+            context->input_count = 0;
+        }
+        break;
+    default:
+        context->err_unk++;
+        context->input_state = 0;
+        break;
+    }
+            
+       return status;
+}
+
+/** 
+ * parse a buffer of nmea data
+ */
+int nmeap_parseBuffer(nmeap_context_t *context,const char *buffer,int *length)
+{
+    int  i;
+    int  status;
+    int  rem;
+    int  tlen;
+    
+    tlen   = *length;
+    rem    = *length;
+    status = 0;
+    /* for each byte in the buffer */
+    for(i=0;i<tlen;i++) {
+        /* decrement remaining byte count */
+        rem--;
+        /* parse the byte */
+        status = nmeap_parse(context,buffer[i]);
+        if (status != 0) {
+            /* message found or error */
+            break;
+        }
+    }
+       
+    /* return remaining byte count */
+    *length = rem;
+       
+    return status;
+}
+
+/** 
+ * standard GPGGA sentence parser 
+ */
+int nmeap_gpgga(nmeap_context_t *context,nmeap_sentence_t *sentence)
+{
+#ifndef NDEBUG 
+    int i;
+#endif
+    
+    /* get pointer to sentence data */
+    nmeap_gga_t *gga = (nmeap_gga_t *)sentence->data;
+    
+    /* if there is a data element, extract data from the tokens */
+       if (gga != 0) {
+               gga->latitude  = nmeap_latitude(context->token[2],context->token[3]);
+               gga->longitude = nmeap_longitude(context->token[4],context->token[5]);
+               gga->altitude  = nmeap_altitude(context->token[9],context->token[10]);
+               gga->time       = atoi(context->token[1]);
+               gga->satellites = atoi(context->token[7]);
+               gga->quality    = atoi(context->token[6]);
+               gga->hdop       = atof(context->token[8]);
+               gga->geoid      = nmeap_altitude(context->token[11],context->token[12]);
+       }
+
+#ifndef NDEBUG    
+    /* print raw input string */
+    printf("%s",context->debug_input);
+    
+    /* print some validation data */
+    printf("%s==%s %02x==%02x\n",context->input_name,sentence->name,context->icks,context->ccks);
+    
+    /* print the tokens */
+    for(i=0;i<context->tokens;i++) {
+        printf("%d:%s\n",i,context->token[i]);
+    }
+#endif   
+
+    /* if the sentence has a callout, call it */
+    if (sentence->callout != 0) {
+        (*sentence->callout)(context,gga,context->user_data);
+    }
+    
+    return NMEAP_GPGGA;
+}
+
+/** 
+ * standard GPRMCntence parser 
+ */
+int nmeap_gprmc(nmeap_context_t *context,nmeap_sentence_t *sentence)
+{
+#ifndef NDEBUG 
+    int i;
+#endif
+
+    /* get pointer to sentence data */
+    nmeap_rmc_t *rmc = (nmeap_rmc_t *)sentence->data;
+    
+       /* if there is a data element, use it */
+       if (rmc != 0) {
+               /* extract data from the tokens */
+               rmc->time       = atoi(context->token[1]);
+               rmc->warn       = *context->token[2];
+               rmc->latitude  = nmeap_latitude(context->token[3],context->token[4]);
+               rmc->longitude = nmeap_longitude(context->token[5],context->token[6]);
+               rmc->speed      = atof(context->token[7]);
+               rmc->course     = atof(context->token[8]);
+               rmc->date       = atoi(context->token[9]);
+               rmc->magvar     = atof(context->token[10]);
+       }
+
+#ifndef NDEBUG    
+    /* print raw input string */
+    printf("%s",context->debug_input);
+    
+    /* print some validation data */
+    printf("%s==%s %02x==%02x\n",context->input_name,sentence->name,context->icks,context->ccks);
+    
+    /* print the tokens */
+    for(i=0;i<context->tokens;i++) {
+        printf("%d:%s\n",i,context->token[i]);
+    }
+#endif   
+
+    /* if the sentence has a callout, call it */
+    if (sentence->callout != 0) {
+        (*sentence->callout)(context,rmc,context->user_data);
+    }
+    
+    return NMEAP_GPRMC;
+}
+
+
diff --git a/bertos/net/nmeap/tst/Makefile b/bertos/net/nmeap/tst/Makefile
new file mode 100644 (file)
index 0000000..e840752
--- /dev/null
@@ -0,0 +1,17 @@
+all : test1 test2 test3 
+
+test1 : $(LIB)/libnmeap.a $(TST)/test1.c 
+       gcc -g -O0 -I $(INC) $(CDEFS) -Wall -Werror -o test1 $(TST)/test1.c $(LIB)/libnmeap.a
+
+test2 : $(LIB)/libnmeap.a $(TST)/test2.c 
+       gcc -g -O0 -I $(INC) $(CDEFS) -Wall -Werror -o test2 $(TST)/test2.c $(LIB)/libnmeap.a
+
+test3 : $(LIB)/libnmeap.a $(TST)/test3.c 
+       gcc -g -O0 -I $(INC) $(CDEFS) -Wall -Werror -o test3 $(TST)/test3.c $(LIB)/libnmeap.a
+
+clean:
+       -$(RM) test1
+       -$(RM) test2
+       -$(RM) test3
+
+
diff --git a/bertos/net/nmeap/tst/test1.c b/bertos/net/nmeap/tst/test1.c
new file mode 100644 (file)
index 0000000..3c5e18b
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License.
+see the file COPYING for more details.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+/*
+========================================================================================================
+EXAMPLE : SETUP FOR GGA AND RMC SENTENCES WITH CHARACTER BY CHARACTER IO
+=======================================================================================================
+*/   
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "nmeap.h"
+
+nmeap_gga_t g_gga;
+
+char test_vector[] = {
+"$GPGGA,123519,3929.946667,N,11946.086667,E,1,08,0.9,545.4,M,46.9,M,,*4A\r\n" /* good */
+"$xyz,1234,asdfadfasdfasdfljsadfkjasdfk\r\n"                                  /* junk */
+"$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n"      /* good */
+"$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*48\r\n"      /* checksum error */
+};
+
+char *pvec = test_vector;
+
+/** simulate character by character IO */
+int readchar() 
+{
+    int ch;
+    if (*pvec == 0) {
+        ch = -1;
+    }
+    else {
+        ch = *pvec++;
+    }
+    return ch;
+}
+
+/** do something with the GGA data */
+static void print_gga(nmeap_gga_t *gga)
+{
+    printf("found GPGGA message %.6f %.6f %.0f %lu %d %d %f %f\n",
+            gga->latitude  ,
+            gga->longitude, 
+            gga->altitude , 
+            gga->time     , 
+            gga->satellites,
+            gga->quality   ,
+            gga->hdop      ,
+            gga->geoid     
+            );
+}
+
+/** called when a gpgga message is received and parsed */
+static void gpgga_callout(nmeap_context_t *context,void *data,void *user_data)
+{
+    nmeap_gga_t *gga = (nmeap_gga_t *)data;
+    
+    printf("-------------callout\n");
+    print_gga(gga);
+}
+
+
+/** do something with the RMC data */
+static void print_rmc(nmeap_rmc_t *rmc)
+{
+    printf("found GPRMC Message %lu %c %.6f %.6f %f %f %lu %f\n",
+            rmc->time,
+            rmc->warn,
+            rmc->latitude,
+            rmc->longitude,
+            rmc->speed,
+            rmc->course,
+            rmc->date,
+            rmc->magvar
+            );
+}
+
+/** called when a gprmc message is received and parsed */
+static void gprmc_callout(nmeap_context_t *context,void *data,void *user_data)
+{
+    nmeap_rmc_t *rmc = (nmeap_rmc_t *)data;
+    
+    printf("-------------callout\n");
+    print_rmc(rmc);
+}
+
+/* ---------------------------------------------------------------------------------------*/
+/* STEP 1 : allocate the data structures. be careful if you put them on the stack because */
+/*          they need to be live for the duration of the parser                           */
+/* ---------------------------------------------------------------------------------------*/
+static nmeap_context_t nmea;      /* parser context */
+static nmeap_gga_t     gga;               /* this is where the data from GGA messages will show up */
+static nmeap_rmc_t     rmc;               /* this is where the data from RMC messages will show up */
+static int             user_data; /* user can pass in anything. typically it will be a pointer to some user data */
+
+int main(int argc,char *argv[])
+{
+    int             status;
+    char            ch;
+    
+       /* ---------------------------------------*/
+       /*STEP 2 : initialize the nmea context    */                                                
+       /* ---------------------------------------*/
+    status = nmeap_init(&nmea,(void *)&user_data);
+    if (status != 0) {
+        printf("nmeap_init %d\n",status);
+        exit(1);
+    }
+    
+       /* ---------------------------------------*/
+       /*STEP 3 : add standard GPGGA parser      */                                                
+       /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPGGA",nmeap_gpgga,gpgga_callout,&gga);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+
+       /* ---------------------------------------*/
+       /*STEP 4 : add standard GPRMC parser      */                                                
+       /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPRMC",nmeap_gprmc,gprmc_callout,&rmc);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+    
+       /* ---------------------------------------*/
+       /*STEP 5 : process input until done       */                                                
+       /* -------------------------------------- */
+    for(;;) {
+               /* ---------------------------------------*/
+               /*STEP 6 : get a byte at a time           */                                                
+               /* -------------------------------------- */
+        ch = readchar();
+        if (ch <= 0) {
+            break;
+        }
+        
+               /* --------------------------------------- */
+               /*STEP 7 : pass it to the parser           */
+               /* status indicates whether a complete msg */
+               /* arrived for this byte                   */
+               /* NOTE : in addition to the return status */
+               /* the message callout will be fired when  */
+               /* a complete message is processed         */
+               /* --------------------------------------- */
+        status = nmeap_parse(&nmea,ch);
+        
+               /* ---------------------------------------*/
+               /*STEP 8 : process the return code        */                                                
+               /* -------------------------------------- */
+        switch(status) {
+        case NMEAP_GPGGA:
+                       /* GOT A GPGGA MESSAGE */
+            printf("-------------switch\n");
+            print_gga(&gga);
+            printf("-------------\n");
+            break;
+        case NMEAP_GPRMC:
+                       /* GOT A GPRMC MESSAGE */
+            printf("-------------switch\n");
+            print_rmc(&rmc);
+            printf("-------------\n");
+            break;
+        default:
+            break;
+        }
+    }
+    
+    return 0;
+}
+
diff --git a/bertos/net/nmeap/tst/test2.c b/bertos/net/nmeap/tst/test2.c
new file mode 100644 (file)
index 0000000..39a700f
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License.
+see the file COPYING for more details.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+/*
+========================================================================================================
+EXAMPLE : SETUP FOR GGA AND RMC SENTENCES WITH CHARACTER BY CHARACTER IO
+=======================================================================================================
+*/   
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "nmeap.h"
+
+nmeap_gga_t g_gga;
+
+char test_vector[] = {
+"$GPGGA,123519,3929.946667,N,11946.086667,E,1,08,0.9,545.4,M,46.9,M,,*4A\r\n" /* good */
+"$xyz,1234,asdfadfasdfasdfljsadfkjasdfk\r\n"                                  /* junk */
+"$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n"      /* good */
+"$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*48\r\n"      /* checksum error */
+};
+
+char *pvec = test_vector;
+
+/** simulate block IO */
+int readbuffer(char *buffer,int len)
+{
+    int i;
+    
+    if (*pvec == 0) {
+        // end of file
+        return -1;
+    }
+    
+    for(i=0;i<len;i++) {
+        /* quit when no more data */
+        if (*pvec == 0) {
+            break;
+        }
+        buffer[i] = *pvec++;
+    }
+    return i;
+}
+
+/** do something with the GGA data */
+static void print_gga(nmeap_gga_t *gga)
+{
+    printf("found GPGGA message %.6f %.6f %.0f %lu %d %d %f %f\n",
+            gga->latitude  ,
+            gga->longitude, 
+            gga->altitude , 
+            gga->time     , 
+            gga->satellites,
+            gga->quality   ,
+            gga->hdop      ,
+            gga->geoid     
+            );
+}
+
+/** called when a gpgga message is received and parsed */
+static void gpgga_callout(nmeap_context_t *context,void *data,void *user_data)
+{
+    nmeap_gga_t *gga = (nmeap_gga_t *)data;
+    
+    printf("-------------callout\n");
+    print_gga(gga);
+}
+
+
+/** do something with the RMC data */
+static void print_rmc(nmeap_rmc_t *rmc)
+{
+    printf("found GPRMC Message %lu %c %.6f %.6f %f %f %lu %f\n",
+            rmc->time,
+            rmc->warn,
+            rmc->latitude,
+            rmc->longitude,
+            rmc->speed,
+            rmc->course,
+            rmc->date,
+            rmc->magvar
+            );
+}
+
+/** called when a gprmc message is received and parsed */
+static void gprmc_callout(nmeap_context_t *context,void *data,void *user_data)
+{
+    nmeap_rmc_t *rmc = (nmeap_rmc_t *)data;
+    
+    printf("-------------callout\n");
+    print_rmc(rmc);
+}
+
+/* ---------------------------------------------------------------------------------------*/
+/* STEP 1 : allocate the data structures. be careful if you put them on the stack because */
+/*          they need to be live for the duration of the parser                           */
+/* ---------------------------------------------------------------------------------------*/
+static nmeap_context_t nmea;      /* parser context */
+static nmeap_gga_t     gga;               /* this is where the data from GGA messages will show up */
+static nmeap_rmc_t     rmc;               /* this is where the data from RMC messages will show up */
+static int             user_data; /* user can pass in anything. typically it will be a pointer to some user data */
+
+int main(int argc,char *argv[])
+{
+    int  status;
+    int  rem;
+       int  offset;
+       int  len;
+       char buffer[32];
+    
+       /* ---------------------------------------*/
+       /*STEP 2 : initialize the nmea context    */                                                
+       /* ---------------------------------------*/
+    status = nmeap_init(&nmea,(void *)&user_data);
+    if (status != 0) {
+        printf("nmeap_init %d\n",status);
+        exit(1);
+    }
+    
+       /* ---------------------------------------*/
+       /*STEP 3 : add standard GPGGA parser      */                                                
+       /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPGGA",nmeap_gpgga,gpgga_callout,&gga);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+
+       /* ---------------------------------------*/
+       /*STEP 4 : add standard GPRMC parser      */                                                
+       /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPRMC",nmeap_gprmc,gprmc_callout,&rmc);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+    
+       /* ---------------------------------------*/
+       /*STEP 5 : process input until done       */                                                
+       /* -------------------------------------- */
+    for(;;) {
+               /* ---------------------------------------*/
+               /*STEP 6 : get a buffer of input          */                                                
+               /* -------------------------------------- */
+        len = rem = readbuffer(buffer,sizeof(buffer));
+        if (len <= 0) {
+            break;
+        }
+        
+               /* ----------------------------------------------*/
+               /*STEP 7 : process input until buffer is used up */                                                
+               /* --------------------------------------------- */
+               offset = 0;
+        while(rem > 0) {
+                       /* --------------------------------------- */
+                       /*STEP 8 : pass it to the parser           */
+                       /* status indicates whether a complete msg */
+                       /* arrived for this byte                   */
+                       /* NOTE : in addition to the return status */
+                       /* the message callout will be fired when  */
+                       /* a complete message is processed         */
+                       /* --------------------------------------- */
+            status = nmeap_parseBuffer(&nmea,&buffer[offset],&rem);
+                       offset += (len - rem); 
+            
+                       /* ---------------------------------------*/
+                       /*STEP 9 : process the return code        */                                                
+                       /* -------------------------------------- */
+            switch(status) {
+            case NMEAP_GPGGA:
+                printf("-------------switch\n");
+                print_gga(&gga);
+                printf("-------------\n");
+                break;
+            case NMEAP_GPRMC:
+                printf("-------------switch\n");
+                print_rmc(&rmc);
+                printf("-------------\n");
+                break;
+            default:
+                break;
+            }
+        }
+    }
+    
+    return 0;
+}
+
diff --git a/bertos/net/nmeap/tst/test3.c b/bertos/net/nmeap/tst/test3.c
new file mode 100644 (file)
index 0000000..250f53c
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License.
+see the file COPYING for more details.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+/*
+========================================================================================================
+EXAMPLE : SETUP FOR GGA AND RMC SENTENCES + A CUSTOM SENTENCE PARSER WITH CHARACTER BY CHARACTER IO
+=======================================================================================================
+*/   
+
+
+/*
+$PGRMF
+
+GARMIN PROPRIETARY GPS Position Fix Data
+
+$PGRMF,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15*HH
+1 = GPS week number
+2 = GPS seconds in current week
+3 = UTC date, ddmmyy format
+4 = UTC time, hhmmss format
+5 = GPS leap second count
+6 = Latitude, dddmm.mmmm format
+7 = Latitude hemisphere, N or S
+8 = Longitude, dddmm.mmmm format
+9 = Longitude hemisphere, E or W
+10 = Mode (M=Manual, A=Automatic)
+11 = Fix type (0=No fix, 1=2D fix, 2=3D fix)
+12 = Speed over ground, kilometres / hour
+13 = Course over ground, degrees true
+14 = PDOP (Position dilution of precision), rounded to nearest integer
+15 = TDOP (Time dilution of precision), rounded to nearest integer
+HH = Checksum 
+*/
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "nmeap.h"
+
+nmeap_gga_t g_gga;
+
+char test_vector[] = {
+"$GPGGA,123519,3929.946667,N,11946.086667,E,1,08,0.9,545.4,M,46.9,M,,*4A\r\n"
+"$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n"
+"$PGRMF,1,100,191105,123519,13,3929.946667,N,12311.12,W,A,2,100.1,181.2,3,8*35\r\n"
+};
+
+char *pvec = test_vector;
+
+/** simulate character by character IO */
+int readchar() 
+{
+    int ch;
+    if (*pvec == 0) {
+        ch = -1;
+    }
+    else {
+        ch = *pvec++;
+    }
+    return ch;
+}
+/* --------------------------------------------------------------*/
+/*STEP 1a : define a data structure to contain the sentence data */                                                
+/* ------------------------------------------------------------- */
+struct garmin_rmf {
+    /* field                            position in sentence */
+    int            week;             /*    1 = GPS week number                                                          */
+    int            seconds_of_week;  /*    2 = GPS seconds in current week                                              */
+    unsigned long  date;             /*    3 = UTC date, ddmmyy format                                                  */
+    unsigned long  time;             /*    4 = UTC time, hhmmss format                                                  */
+    int            leap;             /*    5 = GPS leap second count                                                    */
+    double         lat;              /*  6,7 = Latitude, dddmm.mmmm format (north positive)                             */
+    double         lon;              /*  8,9 = Longitude, dddmm.mmmm format (east positive)                             */
+    int            mode;             /*   10 = Mode (M=Manual, A=Automatic)                                             */
+    int            fix;              /*   11 = Fix type (0=No fix, 1=2D fix, 2=3D fix)                                  */
+    double         speed;            /*   12 = Speed over ground, kilometres / hour                                     */
+    double         course;           /*   13 = Course over ground, degrees true                                         */
+    int            pdop;             /*   14 = PDOP (Position dilution of precision), rounded to nearest integer        */
+    int            tdop;             /*   15 = TDOP (Time dilution of precision), rounded to nearest integer            */
+};
+typedef struct garmin_rmf garmin_rmf_t;
+
+/* --------------------------------------------------------------*/
+/*STEP 1b : define an id value for the message                   */                                                
+/* ------------------------------------------------------------- */
+#define GARMIN_PGRMF (NMEAP_USER + 0)
+
+
+/* --------------------------------------------------------------*/
+/* STEP 1c : write the sentence parser                            */                                                
+/* ------------------------------------------------------------- */
+int custom_pgrmf(nmeap_context_t *context,nmeap_sentence_t *sentence)
+{
+#ifndef NDEBUG 
+    int i;
+#endif
+    
+       /* get pointer to sentence data */
+       garmin_rmf_t *rmf = (garmin_rmf_t *)sentence->data;
+       
+       if (rmf != 0) {
+               /* if the sentence has a data storage element, use it */
+               
+               
+               /* extract data from the tokens */
+               rmf->week            = atoi(context->token[1]);
+               rmf->seconds_of_week = atoi(context->token[2]);
+               rmf->date            = (unsigned long)atol(context->token[3]);
+               rmf->time            = (unsigned long)atol(context->token[4]); 
+               rmf->leap            = atoi(context->token[5]);
+               rmf->lat             = nmeap_latitude(context->token[6],context->token[7]);
+               rmf->lon             = nmeap_longitude(context->token[8],context->token[9]);
+               rmf->mode            = atoi(context->token[10]);
+               rmf->fix             = atoi(context->token[11]);
+               rmf->speed           = atof(context->token[12]);
+               rmf->course          = atof(context->token[13]);
+               rmf->pdop            = atoi(context->token[14]); 
+               rmf->tdop            = atoi(context->token[15]);
+       }
+       /* else there was no data element to store into */
+
+#ifndef NDEBUG    
+    /* print raw input string */
+    printf("%s",context->debug_input);
+    
+    /* print some validation data */
+    printf("%s==%s %02x==%02x\n",context->input_name,sentence->name,context->icks,context->ccks);
+    
+    /* print the tokens */
+    for(i=0;i<context->tokens;i++) {
+        printf("%d:%s\n",i,context->token[i]);
+    }
+#endif   
+
+    /* if the sentence has a callout, call it */
+    if (sentence->callout != 0) {
+        (*sentence->callout)(context,rmf,context->user_data);
+    }
+    
+    return GARMIN_PGRMF;
+}
+
+
+/* -------------------------------------------------------------*/
+/*STEP 2 : write a function to do something with the data       */                                                
+/* ------------------------------------------------------------ */
+static void print_pgrmf(garmin_rmf_t *rmf)
+{
+       assert(rmf != 0);         
+       
+       printf("                    w sec date   time   lp lat       lon         m f spd    crs    p t\n");
+    printf("found PGRMF message %d %d %lu %lu %d %.6f %.6f %d %d %.2f %.2f %d %d\n",
+            rmf->week,                   
+            rmf->seconds_of_week, 
+            rmf->date,            
+            rmf->time,            
+            rmf->leap,            
+            rmf->lat,             
+            rmf->lon,             
+            rmf->mode,            
+            rmf->fix,             
+            rmf->speed,           
+            rmf->course,          
+            rmf->pdop,            
+            rmf->tdop            
+            );
+}
+
+/* -------------------------------------------------------------*/
+/*STEP 3 : if using the callout method, write the callout       */                                                
+/* ------------------------------------------------------------ */
+static void pgrmf_callout(nmeap_context_t *context,void *data,void *user_data)
+{
+    garmin_rmf_t *rmf = (garmin_rmf_t *)data;
+    
+    printf("-------------callout\n");
+    print_pgrmf(rmf);
+}
+
+
+/* ---------------------------------------------------------------------------------------*/
+/* STEP 4 : allocate the data structures. be careful if you put them on the stack because */
+/*          they need to be live for the duration of the parser                           */
+/* ---------------------------------------------------------------------------------------*/
+static nmeap_context_t nmea;       /* parser context */
+static nmeap_gga_t     gga;        /* this is where the data from GGA messages will show up */
+static nmeap_rmc_t     rmc;        /* this is where the data from RMC messages will show up */
+static garmin_rmf_t    rmf;        /* this is where the data from RMF messages will show up */
+static int             user_data; /* user can pass in anything. typically it will be a pointer to some user data */
+
+int main(int argc,char *argv[])
+{
+    int             status;
+    char            ch;
+    
+    /* ---------------------------------------*/
+    /*STEP 5 : initialize the nmea context    */                                                
+    /* ---------------------------------------*/
+    status = nmeap_init(&nmea,(void *)&user_data);
+    if (status != 0) {
+        printf("nmeap_init %d\n",status);
+        exit(1);
+    }
+    
+    /* ---------------------------------------*/
+    /*STEP 6 : add standard GPGGA parser      */
+       /*         (no callout this time)         */
+    /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPGGA",nmeap_gpgga,0,&gga);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+
+    /* ---------------------------------------*/
+    /*STEP 7 : add standard GPRMC parser      */                                                
+       /*         (no callout this time)         */
+    /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPRMC",nmeap_gprmc,0,&rmc);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+    
+    /* ---------------------------------------*/
+    /*STEP 8 : ADD THE CUSTOM PARSER          */                                                
+       /*         with callout         )         */
+    /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"PGRMF",custom_pgrmf,pgrmf_callout,&rmf);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+    /* ---------------------------------------*/
+    /*STEP 9 : process input until done       */                                                
+    /* -------------------------------------- */
+    for(;;) {
+        /* ---------------------------------------*/
+        /*STEP 10: get a byte at a time           */                                                
+        /* -------------------------------------- */
+        ch = readchar();
+        if (ch <= 0) {
+            break;
+        }
+        
+        /* --------------------------------------- */
+        /*STEP 11: pass it to the parser          */
+        /* status indicates whether a complete msg */
+        /* arrived for this byte                   */
+        /* NOTE : in addition to the return status */
+        /* the message callout will be fired when  */
+        /* a complete message is processed         */
+        /* --------------------------------------- */
+        status = nmeap_parse(&nmea,ch);
+        
+        /* ---------------------------------------*/
+        /*STEP 12 : process the return code       */                                                
+        /* -------------------------------------- */
+        switch(status) {
+        case NMEAP_GPGGA:
+            /* GOT A GPGGA MESSAGE */
+            printf("-------------switch\n");
+            printf("GPGGA\n");
+            printf("-------------\n");
+            break;
+        case NMEAP_GPRMC:
+            /* GOT A GPRMC MESSAGE */
+            printf("-------------switch\n");
+            printf("GPRMC\n");
+            printf("-------------\n");
+            break;
+        case GARMIN_PGRMF:
+            /* GOT A PGRMF MESSAGE */
+            printf("-------------switch\n");
+            print_pgrmf(&rmf);
+            printf("-------------\n");
+            break;
+        default:
+            break;
+        }
+    }
+    
+    return 0;
+}
+
diff --git a/bertos/net/nmeap/tst/tst.mak b/bertos/net/nmeap/tst/tst.mak
new file mode 100644 (file)
index 0000000..df5f349
--- /dev/null
@@ -0,0 +1,29 @@
+INCLUDES= ..\inc\nmeap.h ..\inc\nmeap_def.h\r
+CSRC    = nmeap01.c\r
+LIBNAME = ..\lib\libnmeap.lib\r
+\r
+# build everything\r
+all : test1.exe test2.exe test3.exe wingps.exe \r
+\r
+test1.exe : test1.c $(LIBNAME)\r
+       cl /DNDEBUG /c /I..\inc test1.c\r
+       link /OUT:test1.exe test1.obj $(LIBNAME) \r
+       \r
+test2.exe : test2.c $(LIBNAME)\r
+       cl /DNDEBUG /c /I..\inc test2.c\r
+       link /OUT:test2.exe test2.obj $(LIBNAME)\r
+       \r
+test3.exe : test3.c $(LIBNAME)\r
+       cl /DNDEBUG /c /I..\inc test3.c\r
+       link /OUT:test3.exe test3.obj $(LIBNAME)\r
+       \r
+wingps.exe : wingps.c $(LIBNAME)\r
+       cl /DNDEBUG /c /I..\inc wingps.c\r
+       link /OUT:wingps.exe wingps.obj $(LIBNAME)\r
+\r
+# erase all intermediate and output files\r
+clean :\r
+       -erase *.obj\r
+       -erase *.exe\r
+\r
+\r
diff --git a/bertos/net/nmeap/tst/wingps.c b/bertos/net/nmeap/tst/wingps.c
new file mode 100644 (file)
index 0000000..7e6b093
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
+All rights reserved.
+
+This product is licensed for use and distribution under the BSD Open Source License.
+see the file COPYING for more details.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+/*
+========================================================================================================
+EXAMPLE : SETUP FOR GGA AND RMC SENTENCES WITH SERIAL IO FOR WIN32
+=======================================================================================================
+*/   
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "nmeap.h"
+
+/** open a serial port */
+static HANDLE openPort(const char *port,int baud)
+{
+       HANDLE       h;
+       DCB          dcb;
+       COMMTIMEOUTS tmo;
+       int          status;
+
+       /* open the port */
+       h = CreateFile( port,  
+                    GENERIC_READ | GENERIC_WRITE, 
+                    0, 
+                    0, 
+                    OPEN_EXISTING,
+                    0,
+                    0);
+       if (h == INVALID_HANDLE_VALUE) {
+               /* quit on error */
+               return h;
+       }
+   
+
+       /* read current configuration */
+   status = GetCommState(h,&dcb);
+   if (status == 0) {
+          CloseHandle(h);
+          return INVALID_HANDLE_VALUE;
+   }
+
+   /* set the baud rate and other parameters */
+   dcb.BaudRate = baud;
+   dcb.ByteSize = 8;
+   dcb.Parity   = NOPARITY; 
+   dcb.StopBits = ONESTOPBIT;
+
+   /* set configuration */
+   status = SetCommState(h, &dcb);
+   if (status == 0) {
+          CloseHandle(h);
+          return INVALID_HANDLE_VALUE;
+   }
+
+   /* read timeout configuration */
+   status = GetCommTimeouts(h,&tmo);
+   if (status == 0) {
+          CloseHandle(h);
+          return INVALID_HANDLE_VALUE;
+   }
+
+   /* set to indefinite blocking */
+   tmo.ReadIntervalTimeout        = 0;
+   tmo.ReadTotalTimeoutConstant   = 0;
+   tmo.ReadTotalTimeoutMultiplier = 0;
+   status = SetCommTimeouts(h,&tmo);
+   if (status == 0) {
+          CloseHandle(h);
+          return INVALID_HANDLE_VALUE;
+   }
+
+       return h;
+}
+
+/** read a byte (blocking) */
+static int readPort(HANDLE h)
+{
+       BOOL  status;
+       char  ch;
+       DWORD count;
+       status =  ReadFile(h,&ch,1,&count,0);
+       if (status == 0) {
+               return -1;
+       }
+
+       return (int)ch;
+}
+
+
+static void closePort(HANDLE h)
+{
+       CloseHandle(h);
+}
+
+
+/** print current data */
+static void printGps(nmeap_gga_t *gga,nmeap_rmc_t *rmc)
+{
+       printf("%lu %lu %.6f %.6f %.0f %f %f %d %d\n",
+                       gga->time,
+                       rmc->date,
+            gga->latitude  ,
+            gga->longitude, 
+            gga->altitude , 
+                       rmc->course,
+                       rmc->speed,
+            gga->satellites,
+            gga->quality   
+            );
+}
+
+/* ---------------------------------------------------------------------------------------*/
+/* STEP 1 : allocate the data structures. be careful if you put them on the stack because */
+/*          they need to be live for the duration of the parser                           */
+/* ---------------------------------------------------------------------------------------*/
+static nmeap_context_t nmea;      /* parser context */
+static nmeap_gga_t     gga;               /* this is where the data from GGA messages will show up */
+static nmeap_rmc_t     rmc;               /* this is where the data from RMC messages will show up */
+static int             user_data; /* user can pass in anything. typically it will be a pointer to some user data */
+
+int main(int argc,char *argv[])
+{
+    int             status;
+    char            ch;
+       const char     *port;
+       int             baud;
+       HANDLE          h;
+
+       /* require both arguments */
+       if (argc != 3) {
+               printf("%s <comport> <baud>\n",argv[0]);
+               return 1;
+       }
+
+       /* serial port argument */
+       port = argv[1];
+
+       /* baud rate argument */
+       status = sscanf(argv[2],"%d",&baud);
+       if (status != 1) {
+               printf("%s <comport> <baud>\n",argv[0]);
+               printf("invalid <baud> : %s\n",argv[2]);
+               return 1;
+       }
+
+       /** open the serial port */
+       h = openPort(port,baud);
+       if (h == INVALID_HANDLE_VALUE) {
+               printf("can't open port : %s\n",port);
+               return 1;
+       }
+    
+       /* ---------------------------------------*/
+       /*STEP 2 : initialize the nmea context    */                                                
+       /* ---------------------------------------*/
+    status = nmeap_init(&nmea,(void *)&user_data);
+    if (status != 0) {
+        printf("nmeap_init %d\n",status);
+        exit(1);
+    }
+    
+       /* ---------------------------------------*/
+       /*STEP 3 : add standard GPGGA parser      */                                                
+       /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPGGA",nmeap_gpgga,0,&gga);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+
+       /* ---------------------------------------*/
+       /*STEP 4 : add standard GPRMC parser      */                                                
+       /* -------------------------------------- */
+    status = nmeap_addParser(&nmea,"GPRMC",nmeap_gprmc,0,&rmc);
+    if (status != 0) {
+        printf("nmeap_add %d\n",status);
+        exit(1);
+    }
+
+       /* ---------------------------------------*/
+       /*STEP 5 : process input until done       */                                                
+       /* -------------------------------------- */
+    for(;;) {
+               /* ---------------------------------------*/
+               /*STEP 6 : get a byte at a time           */                                                
+               /* -------------------------------------- */
+        ch = readPort(h);
+        if (ch <= 0) {
+            break;
+        }
+        
+               /* --------------------------------------- */
+               /*STEP 7 : pass it to the parser           */
+               /* status indicates whether a complete msg */
+               /* arrived for this byte                   */
+               /* NOTE : in addition to the return status */
+               /* the message callout will be fired when  */
+               /* a complete message is processed         */
+               /* --------------------------------------- */
+        status = nmeap_parse(&nmea,ch);
+        
+               /* ---------------------------------------*/
+               /*STEP 8 : process the return code        */                                                
+               /* -------------------------------------- */
+        switch(status) {
+        case NMEAP_GPGGA:
+                       /* GOT A GPGGA MESSAGE */
+            printGps(&gga,&rmc);
+            break;
+        case NMEAP_GPRMC:
+                       /* GOT A GPRMC MESSAGE */
+            printGps(&gga,&rmc);
+            break;
+        default:
+            break;
+        }
+    }
+
+       /* close and quit */
+       closePort(h);
+    
+    return 0;
+}
diff --git a/bertos/net/nmeap/win32.mak b/bertos/net/nmeap/win32.mak
new file mode 100644 (file)
index 0000000..5c79366
--- /dev/null
@@ -0,0 +1,22 @@
+# directories
+SRC=src
+TST=tst
+
+all :
+       cd $(SRC)
+       $(MAKE) -f nmeap.mak all
+       cd ..\$(TST) 
+       $(MAKE) -f tst.mak all
+       cd ..
+       
+
+clean :
+       cd $(SRC)
+       $(MAKE) -f nmeap.mak clean
+       cd ..\$(TST)
+       $(MAKE) -f tst.mak clean
+       cd ..
+       
+doc  :
+       doxygen
+