r3371 - in developers/olv: . openmoko-agpsui2 openmoko-agpsui2/data openmoko-agpsui2/lto openmoko-agpsui2/lto/.deps openmoko-agpsui2/po openmoko-agpsui2/src
olv at sita.openmoko.org
olv at sita.openmoko.org
Wed Nov 7 18:08:03 CET 2007
Author: olv
Date: 2007-11-07 18:07:34 +0100 (Wed, 07 Nov 2007)
New Revision: 3371
Added:
developers/olv/openmoko-agpsui2/
developers/olv/openmoko-agpsui2/AUTHORS
developers/olv/openmoko-agpsui2/COPYING
developers/olv/openmoko-agpsui2/ChangeLog
developers/olv/openmoko-agpsui2/INSTALL
developers/olv/openmoko-agpsui2/Makefile.am
developers/olv/openmoko-agpsui2/NEWS
developers/olv/openmoko-agpsui2/README
developers/olv/openmoko-agpsui2/autogen.sh
developers/olv/openmoko-agpsui2/configure.ac
developers/olv/openmoko-agpsui2/data/
developers/olv/openmoko-agpsui2/data/Makefile.am
developers/olv/openmoko-agpsui2/data/openmoko-agpsui2.desktop
developers/olv/openmoko-agpsui2/lto/
developers/olv/openmoko-agpsui2/lto/.deps/
developers/olv/openmoko-agpsui2/lto/.deps/http_error_codes.Po
developers/olv/openmoko-agpsui2/lto/.deps/http_fetcher.Po
developers/olv/openmoko-agpsui2/lto/.deps/lto_get.Po
developers/olv/openmoko-agpsui2/lto/.deps/lto_util.Po
developers/olv/openmoko-agpsui2/lto/Makefile.am
developers/olv/openmoko-agpsui2/lto/http_error_codes.c
developers/olv/openmoko-agpsui2/lto/http_error_codes.h
developers/olv/openmoko-agpsui2/lto/http_fetcher.c
developers/olv/openmoko-agpsui2/lto/http_fetcher.h
developers/olv/openmoko-agpsui2/lto/lto_get.c
developers/olv/openmoko-agpsui2/lto/lto_util.c
developers/olv/openmoko-agpsui2/po/
developers/olv/openmoko-agpsui2/po/Makefile.in.in
developers/olv/openmoko-agpsui2/po/POTFILES.in
developers/olv/openmoko-agpsui2/src/
developers/olv/openmoko-agpsui2/src/Makefile.am
developers/olv/openmoko-agpsui2/src/agps.h
developers/olv/openmoko-agpsui2/src/gllin.cpp
developers/olv/openmoko-agpsui2/src/liblto.h
developers/olv/openmoko-agpsui2/src/lto_download.cpp
developers/olv/openmoko-agpsui2/src/lto_download.h
developers/olv/openmoko-agpsui2/src/main.cpp
developers/olv/openmoko-agpsui2/src/nmea.cpp
developers/olv/openmoko-agpsui2/src/nmea.h
developers/olv/openmoko-agpsui2/src/notebook.cpp
developers/olv/openmoko-agpsui2/src/page_AZ.cpp
developers/olv/openmoko-agpsui2/src/page_LTO.cpp
developers/olv/openmoko-agpsui2/src/page_SS.cpp
developers/olv/openmoko-agpsui2/src/page_add.cpp
developers/olv/openmoko-agpsui2/src/page_log.cpp
developers/olv/openmoko-agpsui2/src/page_main.cpp
developers/olv/openmoko-agpsui2/src/page_map.cpp
developers/olv/openmoko-agpsui2/src/page_speed.cpp
developers/olv/openmoko-agpsui2/src/page_stats.cpp
developers/olv/openmoko-agpsui2/src/page_stress.cpp
developers/olv/openmoko-agpsui2/src/page_stress.h
developers/olv/openmoko-agpsui2/src/pm_agps.cpp
developers/olv/openmoko-agpsui2/src/pm_controls.cpp
developers/olv/openmoko-agpsui2/src/sv_bar.h
Log:
Release openmoko-agpsui2 (with modifications) under GPLv2 or later.
The author is Ken Yale from Global Locate (now Broadcom).
Added: developers/olv/openmoko-agpsui2/AUTHORS
===================================================================
--- developers/olv/openmoko-agpsui2/AUTHORS 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/AUTHORS 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1 @@
+Ken Yale
Added: developers/olv/openmoko-agpsui2/COPYING
===================================================================
--- developers/olv/openmoko-agpsui2/COPYING 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/COPYING 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Added: developers/olv/openmoko-agpsui2/ChangeLog
===================================================================
Added: developers/olv/openmoko-agpsui2/INSTALL
===================================================================
--- developers/olv/openmoko-agpsui2/INSTALL 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/INSTALL 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,234 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
Added: developers/olv/openmoko-agpsui2/Makefile.am
===================================================================
--- developers/olv/openmoko-agpsui2/Makefile.am 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/Makefile.am 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,11 @@
+SUBDIRS = src data po
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = aclocal.m4 compile config.guess config.sub \
+ configure depcomp install-sh ltmain.sh \
+ Makefile.in missing config.h.in \
+ intltool-extract intltool-extract.in \
+ intltool-merge intltool-merge.in \
+ intltool-update intltool-update.in \
+ mkinstalldirs
+
Added: developers/olv/openmoko-agpsui2/NEWS
===================================================================
Added: developers/olv/openmoko-agpsui2/README
===================================================================
--- developers/olv/openmoko-agpsui2/README 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/README 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,3 @@
+Testing Application for Hammerhead AGPS Chip.
+
+Modified for generic chips outputing NMEA code.
Added: developers/olv/openmoko-agpsui2/autogen.sh
===================================================================
--- developers/olv/openmoko-agpsui2/autogen.sh 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/autogen.sh 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,4 @@
+#! /bin/sh
+autoreconf -v --install || exit 1
+glib-gettextize --force --copy || exit 1
+./configure --enable-maintainer-mode "$@"
Property changes on: developers/olv/openmoko-agpsui2/autogen.sh
___________________________________________________________________
Name: svn:executable
+
Added: developers/olv/openmoko-agpsui2/configure.ac
===================================================================
--- developers/olv/openmoko-agpsui2/configure.ac 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/configure.ac 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,32 @@
+AC_PREREQ(2.53)
+AC_INIT(openmoko-agpsui2, 1.0.0, noone at broadcom)
+AM_INIT_AUTOMAKE()
+AC_CONFIG_SRCDIR(src/main.cpp)
+AM_CONFIG_HEADER(config.h)
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_STDC_HEADERS
+AC_PROG_LIBTOOL
+
+dnl i18n support
+GETTEXT_PACKAGE=Agpsui
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Gettext package])
+AC_SUBST(GETTEXT_PACKAGE)
+ALL_LINGUAS=""
+AM_GLIB_GNU_GETTEXT
+
+# base deps
+PKG_CHECK_MODULES(OPENMOKO, gtk+-2.0 gthread-2.0)
+LIBS="$LIBS $GTK_LIBS $OPENMOKO_LIBS"
+CFLAGS="$CFLAGS $OPENMOKO_CFLAGS"
+
+# output stuff
+AC_OUTPUT([
+Makefile
+lto/Makefile
+src/Makefile
+po/Makefile.in
+data/Makefile
+])
Added: developers/olv/openmoko-agpsui2/data/Makefile.am
===================================================================
--- developers/olv/openmoko-agpsui2/data/Makefile.am 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/data/Makefile.am 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,17 @@
+#
+# misc. data files
+#
+# None yet
+# dist_pkgdata_DATA =
+
+#
+# desktop integration: .desktop file
+#
+desktopdir = $(datadir)/applications
+dist_desktop_DATA = openmoko-agpsui2.desktop
+
+#
+# desktop integration: application icon
+#
+#appicondir = $(datadir)/pixmaps
+#dist_appicon_DATA = openmoko-calculator.png
Added: developers/olv/openmoko-agpsui2/data/openmoko-agpsui2.desktop
===================================================================
--- developers/olv/openmoko-agpsui2/data/openmoko-agpsui2.desktop 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/data/openmoko-agpsui2.desktop 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Name=AGPS UI
+Comment=AGPS UI
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Exec=openmoko-agpsui2
+Icon=fixme
+Terminal=false
+SingleInstance=true
+StartupNotify=true
Added: developers/olv/openmoko-agpsui2/lto/.deps/http_error_codes.Po
===================================================================
--- developers/olv/openmoko-agpsui2/lto/.deps/http_error_codes.Po 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/.deps/http_error_codes.Po 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1 @@
+# dummy
Added: developers/olv/openmoko-agpsui2/lto/.deps/http_fetcher.Po
===================================================================
--- developers/olv/openmoko-agpsui2/lto/.deps/http_fetcher.Po 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/.deps/http_fetcher.Po 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1 @@
+# dummy
Added: developers/olv/openmoko-agpsui2/lto/.deps/lto_get.Po
===================================================================
--- developers/olv/openmoko-agpsui2/lto/.deps/lto_get.Po 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/.deps/lto_get.Po 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1 @@
+# dummy
Added: developers/olv/openmoko-agpsui2/lto/.deps/lto_util.Po
===================================================================
--- developers/olv/openmoko-agpsui2/lto/.deps/lto_util.Po 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/.deps/lto_util.Po 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1 @@
+# dummy
Added: developers/olv/openmoko-agpsui2/lto/Makefile.am
===================================================================
--- developers/olv/openmoko-agpsui2/lto/Makefile.am 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/Makefile.am 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,11 @@
+localedir = $(datadir)/locale
+
+AM_CPPFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" -DLOCALEDIR=\"$(localedir)\"
+AM_CFLAGS = -Wall -std=c99 -pedantic -DVERSION=HTTP_VERSION
+
+bin_PROGRAMS = lto_get lto_util
+
+lto_get_SOURCES = lto_get.c http_fetcher.c http_error_codes.c
+
+lto_util_SOURCES = lto_util.c
+
Added: developers/olv/openmoko-agpsui2/lto/http_error_codes.c
===================================================================
--- developers/olv/openmoko-agpsui2/lto/http_error_codes.c 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/http_error_codes.c 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,39 @@
+/* http_error_codes.c - Error code declarations
+
+ HTTP Fetcher
+ Copyright (C) 2001, 2003, 2004 Lyle Hanson (lhanson at users.sourceforge.net)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ See LICENSE file for details
+ */
+
+
+ /* Note that '%d' cannot be escaped at this time */
+const char *http_errlist[] =
+ {
+ "Success", /* HF_SUCCESS */
+ "Internal Error. What the hell?!", /* HF_METAERROR */
+ "Got NULL url", /* HF_NULLURL */
+ "Timed out, no metadata for %d seconds", /* HF_HEADTIMEOUT */
+ "Timed out, no data for %d seconds", /* HF_DATATIMEOUT */
+ "Couldn't find return code in HTTP response", /* HF_FRETURNCODE */
+ "Couldn't convert return code in HTTP response",/* HF_CRETURNCODE */
+ "Request returned a status code of %d", /* HF_STATUSCODE */
+ "Couldn't convert Content-Length to integer", /* HF_CONTENTLEN */
+ "Network error (description unavailable)", /* HF_HERROR */
+ "Status code of %d but no Location: field", /* HF_CANTREDIRECT */
+ "Followed the maximum number of redirects (%d)" /* HF_MAXREDIRECTS */
+ };
+
+ /* Used to copy in messages from http_errlist[] and replace %d's with
+ * the value of errorInt. Then we can pass the pointer to THIS */
+char convertedError[128];
Added: developers/olv/openmoko-agpsui2/lto/http_error_codes.h
===================================================================
--- developers/olv/openmoko-agpsui2/lto/http_error_codes.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/http_error_codes.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,42 @@
+/* http_error_codes.h - Error code definitions
+
+ HTTP Fetcher
+ Copyright (C) 2001, 2003, 2004 Lyle Hanson (lhanson at users.sourceforge.net)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ See LICENSE file for details
+
+ */
+
+#ifndef HTTP_ERROR_CODES_H
+#define HTTP_ERROR_CODES_H
+
+/* Error sources */
+#define FETCHER_ERROR 0
+#define ERRNO 1
+#define H_ERRNO 2
+
+/* HTTP Fetcher error codes */
+#define HF_SUCCESS 0
+#define HF_METAERROR 1
+#define HF_NULLURL 2
+#define HF_HEADTIMEOUT 3
+#define HF_DATATIMEOUT 4
+#define HF_FRETURNCODE 5
+#define HF_CRETURNCODE 6
+#define HF_STATUSCODE 7
+#define HF_CONTENTLEN 8
+#define HF_HERROR 9
+#define HF_CANTREDIRECT 10
+#define HF_MAXREDIRECTS 11
+
+#endif
Added: developers/olv/openmoko-agpsui2/lto/http_fetcher.c
===================================================================
--- developers/olv/openmoko-agpsui2/lto/http_fetcher.c 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/http_fetcher.c 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,823 @@
+/* http_fetcher.c - HTTP handling functions
+
+ HTTP Fetcher
+ Copyright (C) 2001, 2003, 2004 Lyle Hanson (lhanson at users.sourceforge.net)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ See LICENSE file for details
+
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include "http_fetcher.h"
+
+extern void updateStatistics(int bytesRead, int contentLength); // KEN
+
+/* Globals */
+int timeout = DEFAULT_READ_TIMEOUT;
+char *userAgent = NULL;
+char *referer = NULL;
+int hideUserAgent = 0;
+int hideReferer = 1;
+static int followRedirects = DEFAULT_REDIRECTS; /* # of redirects to follow */
+extern const char *http_errlist[]; /* Array of HTTP Fetcher error messages */
+extern char convertedError[128]; /* Buffer to used when errors contain %d */
+static int errorSource = 0;
+static int http_errno = 0;
+static int errorInt = 0; /* When the error message has a %d in it,
+ * this variable is inserted */
+
+
+ /*
+ * Actually downloads the page, registering a hit (donation)
+ * If the fileBuf passed in is NULL, the url is downloaded and then
+ * freed; otherwise the necessary space is allocated for fileBuf.
+ * Returns size of download on success, -1 on error is set,
+ */
+int http_fetch(const char *url_tmp, char **fileBuf)
+ {
+ fd_set rfds;
+ struct timeval tv;
+ char headerBuf[HEADER_BUF_SIZE];
+ char *tmp, *url, *pageBuf, *requestBuf = NULL, *host, *charIndex;
+ int sock, bytesRead = 0, contentLength = -1, bufsize = REQUEST_BUF_SIZE;
+ int i,
+ ret = -1,
+ tempSize,
+ selectRet,
+ found = 0, /* For redirects */
+ redirectsFollowed = 0;
+
+
+ if(url_tmp == NULL)
+ {
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_NULLURL;
+ return -1;
+ }
+
+ /* Copy the url passed in into a buffer we can work with, change, etc. */
+ url = malloc(strlen(url_tmp)+1);
+ if(url == NULL)
+ {
+ errorSource = ERRNO;
+ return -1;
+ }
+ strncpy(url, url_tmp, strlen(url_tmp) + 1);
+
+ /* This loop allows us to follow redirects if need be. An afterthought,
+ * added to provide this basic functionality. Will hopefully be designed
+ * better in 2.x.x ;) */
+/* while(!found &&
+ (followRedirects < 0 || redirectsFollowed < followRedirects) )
+ */ do
+ {
+ /* Seek to the file path portion of the url */
+ charIndex = strstr(url, "://");
+ if(charIndex != NULL)
+ {
+ /* url contains a protocol field */
+ charIndex += strlen("://");
+ host = charIndex;
+ charIndex = strchr(charIndex, '/');
+ }
+ else
+ {
+ host = (char *)url;
+ charIndex = strchr(url, '/');
+ }
+
+ /* Compose a request string */
+ requestBuf = malloc(bufsize);
+ if(requestBuf == NULL)
+ {
+ free(url);
+ errorSource = ERRNO;
+ return -1;
+ }
+ requestBuf[0] = 0;
+
+ if(charIndex == NULL)
+ {
+ /* The url has no '/' in it, assume the user is making a root-level
+ * request */
+ tempSize = strlen("GET /") + strlen(HTTP_VERSION) + 2;
+ if(_checkBufSize(&requestBuf, &bufsize, tempSize) ||
+ snprintf(requestBuf, bufsize, "GET / %s\r\n", HTTP_VERSION) < 0)
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ }
+ else
+ {
+ tempSize = strlen("GET ") + strlen(charIndex) +
+ strlen(HTTP_VERSION) + 4;
+ /* + 4 is for ' ', '\r', '\n', and NULL */
+
+ if(_checkBufSize(&requestBuf, &bufsize, tempSize) ||
+ snprintf(requestBuf, bufsize, "GET %s %s\r\n",
+ charIndex, HTTP_VERSION) < 0)
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ }
+
+ /* Null out the end of the hostname if need be */
+ if(charIndex != NULL)
+ *charIndex = 0;
+
+ /* Use Host: even though 1.0 doesn't specify it. Some servers
+ * won't play nice if we don't send Host, and it shouldn't
+ * hurt anything */
+ ret = bufsize - strlen(requestBuf); /* Space left in buffer */
+ tempSize = (int)strlen("Host: ") + (int)strlen(host) + 3;
+ /* +3 for "\r\n\0" */
+ if(_checkBufSize(&requestBuf, &bufsize, tempSize + 128))
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ strcat(requestBuf, "Host: ");
+ strcat(requestBuf, host);
+ strcat(requestBuf, "\r\n");
+
+ if(!hideReferer && referer != NULL) /* NO default referer */
+ {
+ tempSize = (int)strlen("Referer: ") + (int)strlen(referer) + 3;
+ /* + 3 is for '\r', '\n', and NULL */
+ if(_checkBufSize(&requestBuf, &bufsize, tempSize))
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ strcat(requestBuf, "Referer: ");
+ strcat(requestBuf, referer);
+ strcat(requestBuf, "\r\n");
+ }
+
+ if(!hideUserAgent && userAgent == NULL)
+ {
+ tempSize = (int)strlen("User-Agent: ") +
+ (int)strlen(DEFAULT_USER_AGENT) + (int)strlen(VERSION) + 4;
+ /* + 4 is for '\', '\r', '\n', and NULL */
+ if(_checkBufSize(&requestBuf, &bufsize, tempSize))
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ strcat(requestBuf, "User-Agent: ");
+ strcat(requestBuf, DEFAULT_USER_AGENT);
+ strcat(requestBuf, "/");
+ strcat(requestBuf, VERSION);
+ strcat(requestBuf, "\r\n");
+ }
+ else if(!hideUserAgent)
+ {
+ tempSize = (int)strlen("User-Agent: ") + (int)strlen(userAgent) + 3;
+ /* + 3 is for '\r', '\n', and NULL */
+ if(_checkBufSize(&requestBuf, &bufsize, tempSize))
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ strcat(requestBuf, "User-Agent: ");
+ strcat(requestBuf, userAgent);
+ strcat(requestBuf, "\r\n");
+ }
+
+ tempSize = (int)strlen("Connection: Close\r\n\r\n");
+ if(_checkBufSize(&requestBuf, &bufsize, tempSize))
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ strcat(requestBuf, "Connection: Close\r\n\r\n");
+
+ /* Now free any excess memory allocated to the buffer */
+ tmp = realloc(requestBuf, strlen(requestBuf) + 1);
+ if(tmp == NULL)
+ {
+ free(url);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ requestBuf = tmp;
+
+ sock = makeSocket(host); /* errorSource set within makeSocket */
+ if(sock == -1) { free(url); free(requestBuf); return -1;}
+
+ free(url);
+ url = NULL;
+
+ if(write(sock, requestBuf, strlen(requestBuf)) == -1)
+ {
+ close(sock);
+ free(requestBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+
+ free(requestBuf);
+ requestBuf = NULL;
+
+ /* Grab enough of the response to get the metadata */
+ ret = _http_read_header(sock, headerBuf); /* errorSource set within */
+ if(ret < 0) { close(sock); return -1; }
+
+ /* Get the return code */
+ charIndex = strstr(headerBuf, "HTTP/");
+ if(charIndex == NULL)
+ {
+ close(sock);
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_FRETURNCODE;
+ return -1;
+ }
+ while(*charIndex != ' ')
+ charIndex++;
+ charIndex++;
+
+ ret = sscanf(charIndex, "%d", &i);
+ if(ret != 1)
+ {
+ close(sock);
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_CRETURNCODE;
+ return -1;
+ }
+ if(i<200 || i>307)
+ {
+ close(sock);
+ errorInt = i; /* Status code, to be inserted in error string */
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_STATUSCODE;
+ return -1;
+ }
+
+ /* If a redirect, repeat operation until final URL is found or we
+ * redirect followRedirects times. Note the case sensitive "Location",
+ * should probably be made more robust in the future (without relying
+ * on the non-standard strcasecmp()).
+ * This bit mostly by Dean Wilder, tweaked by me */
+ if(i >= 300)
+ {
+ redirectsFollowed++;
+
+ /* Pick up redirect URL, allocate new url, and repeat process */
+ charIndex = strstr(headerBuf, "Location:");
+ if(!charIndex)
+ {
+ close(sock);
+ errorInt = i; /* Status code, to be inserted in error string */
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_CANTREDIRECT;
+ return -1;
+ }
+ charIndex += strlen("Location:");
+ /* Skip any whitespace... */
+ while(*charIndex != '\0' && isspace(*charIndex))
+ charIndex++;
+ if(*charIndex == '\0')
+ {
+ close(sock);
+ errorInt = i; /* Status code, to be inserted in error string */
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_CANTREDIRECT;
+ return -1;
+ }
+
+ i = strcspn(charIndex, " \r\n");
+ if(i > 0)
+ {
+ url = (char *)malloc(i + 1);
+ strncpy(url, charIndex, i);
+ url[i] = '\0';
+ }
+ else
+ /* Found 'Location:' but contains no URL! We'll handle it as
+ * 'found', hopefully the resulting document will give the user
+ * a hint as to what happened. */
+ found = 1;
+ }
+ else
+ found = 1;
+ } while(!found &&
+ (followRedirects < 0 || redirectsFollowed <= followRedirects) );
+
+ if(url) /* Redirection code may malloc this, then exceed followRedirects */
+ {
+ free(url);
+ url = NULL;
+ }
+
+ if(redirectsFollowed >= followRedirects && !found)
+ {
+ close(sock);
+ errorInt = followRedirects; /* To be inserted in error string */
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_MAXREDIRECTS;
+ return -1;
+ }
+
+ /*
+ * Parse out about how big the data segment is.
+ * Note that under current HTTP standards (1.1 and prior), the
+ * Content-Length field is not guaranteed to be accurate or even present.
+ * I just use it here so I can allocate a ballpark amount of memory.
+ *
+ * Note that some servers use different capitalization
+ */
+ charIndex = strstr(headerBuf, "Content-Length:");
+ if(charIndex == NULL)
+ charIndex = strstr(headerBuf, "Content-length:");
+
+ if(charIndex != NULL)
+ {
+ ret = sscanf(charIndex + strlen("content-length: "), "%d",
+ &contentLength);
+ if(ret < 1)
+ {
+ close(sock);
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_CONTENTLEN;
+ return -1;
+ }
+ }
+
+ /* Allocate enough memory to hold the page */
+ if(contentLength == -1)
+ contentLength = DEFAULT_PAGE_BUF_SIZE;
+
+ pageBuf = (char *)malloc(contentLength);
+ if(pageBuf == NULL)
+ {
+ close(sock);
+ errorSource = ERRNO;
+ return -1;
+ }
+
+ updateStatistics(bytesRead, contentLength); // KEN
+
+ /* Begin reading the body of the file */
+ while(ret > 0)
+ {
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ if(timeout >= 0)
+ selectRet = select(sock+1, &rfds, NULL, NULL, &tv);
+ else /* No timeout, can block indefinately */
+ selectRet = select(sock+1, &rfds, NULL, NULL, NULL);
+
+ if(selectRet == 0)
+ {
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_DATATIMEOUT;
+ errorInt = timeout;
+ close(sock);
+ free(pageBuf);
+ return -1;
+ }
+ else if(selectRet == -1)
+ {
+ close(sock);
+ free(pageBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+
+ ret = read(sock, pageBuf + bytesRead, contentLength);
+ if(ret == -1)
+ {
+ close(sock);
+ free(pageBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+
+ bytesRead += ret;
+
+ updateStatistics(bytesRead, contentLength); // KEN
+
+ if(ret > 0)
+ {
+ /* To be tolerant of inaccurate Content-Length fields, we'll
+ * allocate another read-sized chunk to make sure we have
+ * enough room.
+ */
+ tmp = (char *)realloc(pageBuf, bytesRead + contentLength);
+ if(tmp == NULL)
+ {
+ close(sock);
+ free(pageBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ pageBuf = tmp;
+ }
+ }
+
+ /*
+ * The download buffer is too large. Trim off the safety padding.
+ * Note that we add one NULL byte to the end of the data, as it may not
+ * already be NULL terminated and we can't be sure what type of data it
+ * is or what the caller will do with it.
+ */
+ tmp = (char *)realloc(pageBuf, bytesRead + 1);
+ /* tmp shouldn't be null, since we're _shrinking_ the buffer,
+ * and if it DID fail, we could go on with the too-large buffer,
+ * but something would DEFINATELY be wrong, so we'll just give
+ * an error message */
+ if(tmp == NULL)
+ {
+ close(sock);
+ free(pageBuf);
+ errorSource = ERRNO;
+ return -1;
+ }
+ pageBuf = tmp;
+ pageBuf[bytesRead] = '\0'; /* NULL terminate the data */
+
+ if(fileBuf == NULL) /* They just wanted us to "hit" the url */
+ free(pageBuf);
+ else
+ *fileBuf = pageBuf;
+
+ close(sock);
+ return bytesRead;
+ }
+
+
+
+ /*
+ * Changes the User Agent. Returns 0 on success, -1 on error.
+ */
+int http_setUserAgent(const char *newAgent)
+ {
+ static int freeOldAgent = 0; /* Indicates previous malloc's */
+ char *tmp;
+
+ if(newAgent == NULL)
+ {
+ if(freeOldAgent) free(userAgent);
+ userAgent = NULL;
+ hideUserAgent = 1;
+ }
+ else
+ {
+ tmp = (char *)malloc(strlen(newAgent));
+ if(tmp == NULL) { errorSource = ERRNO; return -1; }
+ if(freeOldAgent) free(userAgent);
+ userAgent = tmp;
+ strcpy(userAgent, newAgent);
+ freeOldAgent = 1;
+ hideUserAgent = 0;
+ }
+
+ return 0;
+ }
+
+
+
+ /*
+ * Changes the Referer. Returns 0 on success, -1 on error
+ */
+int http_setReferer(const char *newReferer)
+ {
+ static int freeOldReferer = 0; /* Indicated previous malloc's */
+ char *tmp;
+
+ if(newReferer == NULL)
+ {
+ if(freeOldReferer) free(referer);
+ referer = NULL;
+ hideReferer = 1;
+ }
+ else
+ {
+ tmp = (char *)malloc(strlen(newReferer));
+ if(tmp == NULL) { errorSource = ERRNO; return -1; }
+ if(freeOldReferer) free(referer);
+ referer = tmp;
+ strcpy(referer, newReferer);
+ freeOldReferer = 1;
+ hideReferer = 0;
+ }
+
+ return 0;
+ }
+
+
+
+ /*
+ * Changes the amount of time that HTTP Fetcher will wait for data
+ * before timing out on reads
+ */
+void http_setTimeout(int seconds) { timeout = seconds; }
+
+
+
+ /*
+ * Changes the number of HTTP redirects HTTP Fetcher will automatically
+ * follow. If a request returns a status code of 3XX and contains
+ * a "Location:" field, the library will transparently follow up to
+ * the specified number of redirects. With this implementation
+ * (which is just a stopgap, really) the caller won't be aware of any
+ * redirection and will assume the returned document came from the original
+ * URL.
+ * To disable redirects, pass a 0. To follow unlimited redirects (probably
+ * unwise), pass a negative value. The default is to follow 3 redirects.
+ */
+void http_setRedirects(int redirects) { followRedirects = redirects; }
+
+
+
+ /*
+ * Puts the filename portion of the url into 'filename'.
+ * Returns:
+ * 0 on success
+ * 1 when url contains no end filename (i.e., 'www.foo.com/'),
+ * and **filename should not be assumed to be valid
+ * -1 on error
+ */
+int http_parseFilename(const char *url, char **filename)
+ {
+ char *ptr;
+
+ if(url == NULL)
+ {
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_NULLURL;
+ return -1;
+ }
+
+ ptr = (char *)rindex(url, '/');
+ if(ptr == NULL)
+ /* Root level request, apparently */
+ return 1;
+
+ ptr++;
+ if(*ptr == '\0') return 1;
+
+ *filename = (char *)malloc(strlen(ptr));
+ if(*filename == NULL) { errorSource = ERRNO; return -1; }
+ strcpy(*filename, ptr);
+
+ return 0;
+ }
+
+
+
+ /* Depending on the source of error, calls either perror() or prints
+ * an HTTP Fetcher error message to stdout */
+void http_perror(const char *string)
+ {
+ if(errorSource == ERRNO)
+ perror(string);
+ else if(errorSource == H_ERRNO)
+ herror(string);
+ else if(errorSource == FETCHER_ERROR)
+ {
+ const char *stringIndex; // KEN
+
+ if(strstr(http_errlist[http_errno], "%d") == NULL)
+ {
+ fputs(string, stderr);
+ fputs(": ", stderr);
+ fputs(http_errlist[http_errno], stderr);
+ fputs("\n", stderr);
+ }
+ else
+ {
+ /* The error string has a %d in it, we need to insert errorInt */
+ stringIndex = http_errlist[http_errno];
+ while(*stringIndex != '%') /* Print up to the %d */
+ {
+ fputc(*stringIndex, stderr);
+ stringIndex++;
+ }
+ fprintf(stderr, "%d", errorInt); /* Print the number */
+ stringIndex += 2; /* Skip past the %d */
+ while(*stringIndex != 0) /* Print up to the end NULL */
+ {
+ fputc(*stringIndex, stderr);
+ stringIndex++;
+ }
+ fputs("\n", stderr);
+ }
+ }
+ }
+
+
+
+ /*
+ * Returns a pointer to the current error description message. The
+ * message pointed to is only good until the next call to http_strerror(),
+ * so if you need to hold on to the message for a while you should make
+ * a copy of it
+ */
+const char *http_strerror()
+ {
+ extern int errno;
+
+ if(errorSource == ERRNO)
+ return strerror(errno);
+ else if(errorSource == H_ERRNO)
+#ifdef HAVE_HSTRERROR
+ return hstrerror(h_errno);
+#else
+ return http_errlist[HF_HERROR];
+#endif
+ else if(errorSource == FETCHER_ERROR)
+ {
+ if(strstr(http_errlist[http_errno], "%d") == NULL)
+ return http_errlist[http_errno];
+ else
+ {
+ /* The error string has a %d in it, we need to insert errorInt.
+ * convertedError[128] has been declared for that purpose */
+ const char* stringIndex; // KEN
+ const char* originalError; // KEN
+
+ originalError = http_errlist[http_errno];
+ convertedError[0] = 0; /* Start off with NULL */
+ stringIndex = strstr(originalError, "%d");
+ strncat(convertedError, originalError, /* Copy up to %d */
+ abs(stringIndex - originalError));
+ sprintf(&convertedError[strlen(convertedError)],"%d",errorInt);
+ stringIndex += 2; /* Skip past the %d */
+ strcat(convertedError, stringIndex);
+
+ return convertedError;
+ }
+ }
+
+ return http_errlist[HF_METAERROR]; /* Should NEVER happen */
+ }
+
+
+ /*
+ * Reads the metadata of an HTTP response.
+ * Perhaps a little inefficient, as it reads 1 byte at a time, but
+ * I don't think it's that much of a loss (most headers aren't HUGE).
+ * Returns:
+ * # of bytes read on success, or
+ * -1 on error
+ */
+int _http_read_header(int sock, char *headerPtr)
+ {
+ fd_set rfds;
+ struct timeval tv;
+ int bytesRead = 0, newlines = 0, ret, selectRet;
+
+ while(newlines != 2 && bytesRead != HEADER_BUF_SIZE)
+ {
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ if(timeout >= 0)
+ selectRet = select(sock+1, &rfds, NULL, NULL, &tv);
+ else /* No timeout, can block indefinately */
+ selectRet = select(sock+1, &rfds, NULL, NULL, NULL);
+
+ if(selectRet == 0)
+ {
+ errorSource = FETCHER_ERROR;
+ http_errno = HF_HEADTIMEOUT;
+ errorInt = timeout;
+ return -1;
+ }
+ else if(selectRet == -1) { errorSource = ERRNO; return -1; }
+
+ ret = read(sock, headerPtr, 1);
+ if(ret == -1) { errorSource = ERRNO; return -1; }
+ bytesRead++;
+
+ if(*headerPtr == '\r') /* Ignore CR */
+ {
+ /* Basically do nothing special, just don't set newlines
+ * to 0 */
+ headerPtr++;
+ continue;
+ }
+ else if(*headerPtr == '\n') /* LF is the separator */
+ newlines++;
+ else
+ newlines = 0;
+
+ headerPtr++;
+ }
+
+ headerPtr -= 3; /* Snip the trailing LF's */
+ *headerPtr = '\0';
+ return bytesRead;
+ }
+
+
+
+ /*
+ * Opens a TCP socket and returns the descriptor
+ * Returns:
+ * socket descriptor, or
+ * -1 on error
+ */
+int makeSocket(const char *host)
+ {
+ int sock; /* Socket descriptor */
+ struct sockaddr_in sa; /* Socket address */
+ struct hostent *hp; /* Host entity */
+ int ret;
+ int port;
+ char *p;
+
+ /* Check for port number specified in URL */
+ p = strchr(host, ':');
+ if(p)
+ {
+ port = atoi(p + 1);
+ *p = '\0';
+ }
+ else
+ port = PORT_NUMBER;
+
+ hp = gethostbyname(host);
+ if(hp == NULL) { errorSource = H_ERRNO; return -1; }
+
+ /* Copy host address from hostent to (server) socket address */
+ memcpy((char *)&sa.sin_addr, (char *)hp->h_addr, hp->h_length);
+ sa.sin_family = hp->h_addrtype; /* Set service sin_family to PF_INET */
+ sa.sin_port = htons(port); /* Put portnum into sockaddr */
+
+ sock = socket(hp->h_addrtype, SOCK_STREAM, 0);
+ if(sock == -1) { errorSource = ERRNO; return -1; }
+
+ ret = connect(sock, (struct sockaddr *)&sa, sizeof(sa));
+ if(ret == -1) { errorSource = ERRNO; return -1; }
+
+ return sock;
+ }
+
+
+
+ /*
+ * Determines if the given NULL-terminated buffer is large enough to
+ * concatenate the given number of characters. If not, it attempts to
+ * grow the buffer to fit.
+ * Returns:
+ * 0 on success, or
+ * -1 on error (original buffer is unchanged).
+ */
+int _checkBufSize(char **buf, int *bufsize, int more)
+ {
+ char *tmp;
+ int roomLeft = *bufsize - (strlen(*buf) + 1);
+ if(roomLeft > more)
+ return 0;
+ tmp = realloc(*buf, *bufsize + more + 1);
+ if(tmp == NULL)
+ return -1;
+ *buf = tmp;
+ *bufsize += more + 1;
+ return 0;
+ }
Added: developers/olv/openmoko-agpsui2/lto/http_fetcher.h
===================================================================
--- developers/olv/openmoko-agpsui2/lto/http_fetcher.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/http_fetcher.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,159 @@
+/* http_fetcher.h - HTTP handling functions
+
+ HTTP Fetcher
+ Copyright (C) 2001, 2003, 2004 Lyle Hanson (lhanson at users.sourceforge.net)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ See LICENSE file for details
+
+ */
+
+#ifndef HTTP_FETCHER_H
+#define HTTP_FETCHER_H
+
+#include "http_error_codes.h"
+
+#define PORT_NUMBER 80
+#define HTTP_VERSION "HTTP/1.0"
+#define DEFAULT_USER_AGENT "HTTP Fetcher"
+#define DEFAULT_READ_TIMEOUT 30 /* Seconds to wait before giving up
+ * when no data is arriving */
+
+#define REQUEST_BUF_SIZE 1024
+#define HEADER_BUF_SIZE 1024
+#define DEFAULT_PAGE_BUF_SIZE 1024 * 200 /* 200K should hold most things */
+#define DEFAULT_REDIRECTS 3 /* Number of HTTP redirects to follow */
+
+
+
+/******************************************************************************/
+/**************** Function declarations and descriptions **********************/
+/******************************************************************************/
+
+/*
+ * [!!! NOTE !!!] All HTTP Fetcher functions return -1 on error. You can
+ * then either call http_perror to print the error message or call
+ * http_strerror to get a pointer to it
+ */
+
+
+ /*
+ * Download the page, registering a hit. If you pass it a NULL for fileBuf,
+ * 'url' will be requested but will not remain in memory (useful for
+ * simply registering a hit). Otherwise necessary space will be allocated
+ * and will be pointed to by fileBuf. Note that a NULL byte is added to
+ * the data, so the actual buffer will be the file size + 1.
+ * Returns:
+ * # of bytes downloaded, or
+ * -1 on error
+ */
+int http_fetch(const char *url, char **fileBuf);
+
+ /*
+ * Changes the User Agent (shown to the web server with each request)
+ * Send it NULL to avoid telling the server a User Agent
+ * By default, the User Agent is sent (The default one unless changed)
+ * Returns:
+ * 0 on success, or
+ * -1 on error (previous value for agent remains unchanged)
+ */
+int http_setUserAgent(const char *newAgent);
+
+ /*
+ * Changes the Referer (shown to the web server with each request)
+ * Send it NULL to avoid thelling the server a Referer
+ * By default, no Referer is sent
+ * Returns:
+ * 0 on success, or
+ * -1 on error
+ */
+int http_setReferer(const char *newReferer);
+
+ /*
+ * Changes the maximum amount of time that HTTP Fetcher will wait on
+ * data. If this many seconds elapses without more data from the
+ * server, http_fetch will return with an error.
+ * If you pass a value less than 0, reads will not time out, potentially
+ * waiting forever (or until data shows up, whichever comes first)
+ */
+void http_setTimeout(int seconds);
+
+ /*
+ * Changes the number of HTTP redirects HTTP Fetcher will automatically
+ * follow. If a request returns a status code of 3XX and contains
+ * a "Location:" field, the library will transparently follow up to
+ * the specified number of redirects. With this implementation
+ * (which is just a stopgap, really) the caller won't be aware of any
+ * redirection and will assume the returned document came from the original
+ * URL.
+ * To disable redirects, pass a 0. To follow unlimited redirects (probably
+ * unwise), pass a negative value. The default is to follow 3 redirects.
+ */
+void http_setRedirects(int redirects);
+
+ /*
+ * Takes a url and puts the filename portion of it into 'filename'.
+ * Returns:
+ * 0 on success, or
+ * 1 when url contains no end filename (i.e., "www.foo.com/")
+ * and **filename should not be assumed to point to anything), or
+ * -1 on error
+ */
+int http_parseFilename(const char *url, char **filename);
+
+ /*
+ * Works like perror. If an HTTP Fetcher function ever returns an
+ * error (-1), this will print a descriptive message to standard output
+ */
+void http_perror(const char *string);
+
+ /*
+ * Returns a pointer to the current error description message. The
+ * message pointed to is only good until the next call to http_strerror(),
+ * so if you need to hold on to the message for a while you should make
+ * a copy of it.
+ */
+const char *http_strerror();
+
+
+
+/******************************************************************************/
+/**** The following functions are used INTERNALLY by http_fetcher *************/
+/******************************************************************************/
+
+ /*
+ * Reads the metadata of an HTTP response. On success returns the number
+ * Returns:
+ * # of bytes read on success, or
+ * -1 on error
+ */
+int _http_read_header(int sock, char *headerPtr);
+
+ /*
+ * Opens a TCP socket and returns the descriptor
+ * Returns:
+ * socket descriptor, or
+ * -1 on error
+ */
+int makeSocket(const char *host);
+
+ /*
+ * Determines if the given NULL-terminated buffer is large enough to
+ * concatenate the given number of characters. If not, it attempts to
+ * grow the buffer to fit.
+ * Returns:
+ * 0 on success, or
+ * -1 on error (original buffer is unchanged).
+ */
+int _checkBufSize(char **buf, int *bufsize, int more);
+
+#endif
Added: developers/olv/openmoko-agpsui2/lto/lto_get.c
===================================================================
--- developers/olv/openmoko-agpsui2/lto/lto_get.c 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/lto_get.c 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,281 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <memory.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "http_fetcher.h"
+
+const char* argv0 = "<unknown>";
+const char* file = 0;
+const char* url = 0;
+int fd = -1;
+int debug = 0;
+int sim = 0;
+
+void updateStatistics(int bytesRead, int contentLength);
+void lto_progress();
+int sim_fetch(const char* url, char** fileBuf);
+
+// const char* default_url = "http://gllto.glpals.com/7day/v2/latest/lto2.dat";
+const char* default_url = "http://66.35.236.20/7day/v2/latest/lto2.dat";
+const char* default_file = "./lto2.dat";
+
+//-----------------------------------------------------------------------------
+//
+// lto_get()
+//
+// USAGE:
+// lto_get -default [+DEBUG]
+// lto_get <url> <file> [+DEBUG]
+//
+// DESCRPIPTION:
+// copy file from <url> to <file>
+// Report to stdout:
+// <done>=N When done. N is the file size in bytes.
+// Exit 0.
+//
+// <percent>=0..100
+// During the download itself.
+//
+// <progress>=A..Z,a..z
+// During the download itself.
+//
+// <err>="...." Upon error.
+// Exit 1.
+//
+//-----------------------------------------------------------------------------
+
+int
+main(int argc, char** argv)
+{
+ int i = 0;
+
+ argv0 = argv[i];
+
+ for (++i; i < argc; ++i)
+ {
+ const char* a = argv[i];
+
+ if (!strcmp(a, "-help"))
+ {
+ printf( "<help>=\"\n"
+ "lto_get version 0.04 %s\n"
+ "lto_get <url> <file> [opts]\n"
+ "lto_get -default [opts]\n"
+ " defaults are: url %s\n"
+ " file %s\n"
+ "Options:\n"
+ " +DEBUG enable more output\n"
+ " +SIM simulate download and file creation\n"
+ "\n",
+ __DATE__,
+ default_url, default_file);
+ return 1;
+ }
+
+ if (!strcmp(a, "-default"))
+ {
+ url = default_url;
+ file = default_file;
+ continue;
+ }
+
+ if (!strcmp(a,"+DEBUG"))
+ {
+ debug = 1;
+ continue;
+ }
+
+ if (!strcmp(a,"+SIM"))
+ {
+ sim = 1;
+ continue;
+ }
+
+ if (!url)
+ {
+ url = a;
+ continue;
+ }
+ if (!file)
+ {
+ file = a;
+ continue;
+ }
+ }
+
+ if (debug)
+ {
+ printf("<debug>=\"url %s\"\n", (url) ? url : "<null>" );
+ printf("<debug>=\"file %s\"\n", (file) ? file : "<null>" );
+ }
+
+ if (!url || !file)
+ {
+ printf("<err>=\"%s missing parameters\"\n", argv0);
+ return 1;
+ }
+
+ lto_progress();
+
+ fd = open(file, O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH );
+ if (fd < 0)
+ {
+ printf("<err>=\"%s: open(%s) error %d %s\"\n", argv0, file,
+ errno, strerror(errno));
+ return 2;
+ }
+
+ lto_progress();
+
+ http_setTimeout(10); // 10 seconds between packets max.
+{
+ char* fileBuf;
+ int write_size = 0;
+ int http_size;
+
+ if (sim)
+ {
+ http_size = sim_fetch(url, &fileBuf);
+ }
+ else
+ {
+ http_size = http_fetch(url, &fileBuf);
+ }
+
+ if (http_size <= 0)
+ {
+ printf("<err>=\"%s: http get(%s) error %s\"\n", argv0, url,
+ http_strerror());
+ close(fd);
+ return 2;
+ }
+ lto_progress();
+
+ write_size = write(fd, fileBuf, http_size);
+ lto_progress();
+ close(fd);
+ lto_progress();
+ if (write_size != http_size)
+ {
+ printf("<err>=\"%s: write(%s,%d) error %d %s\"\n",
+ argv0, file, http_size,
+ errno, strerror(errno));
+ return 2;
+ }
+ printf("<done>=%d\n", write_size);
+
+ return 0;
+}
+}
+
+//-----------------------------------------------------------------------------
+//
+// updateStatistics()
+//
+// DESCRPIPTION:
+// Report data transfer percentage if we've made more than 1.9%
+// progress.
+//
+// Maintain the download statistics in terms of percent*10
+//
+//-----------------------------------------------------------------------------
+
+void
+updateStatistics(int bytesRead, int contentLength)
+{
+ static int last_percent_10 = -100;
+ int percent_10 = ((bytesRead * 1000) + 5) / contentLength;
+
+ // if (debug)
+ // {
+ // printf("<debug>=\"percent_10(%d/%d = %d\"\n",
+ // bytesRead, contentLength, percent_10);
+ // }
+
+ if (((percent_10 - last_percent_10) > 19) || debug)
+ {
+ last_percent_10 = percent_10;
+ printf("<percent>=%d\n", percent_10/10);
+ fflush(stdout);
+ }
+}
+
+//-----------------------------------------------------------------------------
+//
+// lto_progress()
+//
+// DESCRPIPTION:
+// Report the progress "A" to "Z". then "a" to "z" (if needed)
+//
+//-----------------------------------------------------------------------------
+
+void
+lto_progress()
+{
+ static char progress = 'a';
+ if (debug)
+ {
+ printf("<progress>=%c\n", progress);
+ fflush(stdout);
+ }
+ if (++progress == ('Z' + 1))
+ {
+ progress = 'a';
+ }
+ else if (progress == ('z' + 1))
+ {
+ progress = 'A';
+ }
+}
+
+//-----------------------------------------------------------------------------
+//
+// sim_fetch()
+//
+// DESCRPIPTION:
+// Simulate the downloading of the code by sleep and dummy data
+//
+//-----------------------------------------------------------------------------
+
+int
+sim_fetch(const char* url, char** fileBuf)
+{
+ const int fileSize = 10000;
+ const int nLoops = 18;
+ const int loopSize = fileSize/nLoops;
+ int written = 0;
+ int loop;
+
+ char* data = (char*) malloc(fileSize);
+
+ if (debug)
+ {
+ printf("<debug>=\"simulating file size %d in %d loops\"\n",
+ fileSize, nLoops);
+ }
+
+ for (loop = 0; loop <= nLoops; ++loop)
+ {
+ updateStatistics(written, fileSize);
+ sleep(1);
+ written += loopSize;
+ if (written > fileSize)
+ {
+ written = fileSize;
+ updateStatistics(written, fileSize);
+ break;
+ }
+ }
+
+ *fileBuf = data;
+ return fileSize;
+}
Added: developers/olv/openmoko-agpsui2/lto/lto_util.c
===================================================================
--- developers/olv/openmoko-agpsui2/lto/lto_util.c 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/lto/lto_util.c 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,209 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static int read_output(int fd);
+
+//-----------------------------------------------------------------------------
+//
+// lto_util()
+//
+// USAGE:
+// lto_util
+//
+// DESCRPIPTION:
+// Test the lto_get program.
+// Fork and exec lto_get() then
+// track its progress and errors,
+// then wait for it to exit.
+//
+//-----------------------------------------------------------------------------
+
+int
+main(int argc, char** argv)
+{
+ int fd[2];
+ int err = pipe(fd);
+ int pid = 0;
+
+ const char* lto_get = "./lto_get";
+ const char* url = "http://gllto.glpals.com/7day/v2/latest/lto2.dat";
+ const char* file = "./lto2.dat";
+ const char* debug = "+DEBUG";
+
+ struct stat st;
+
+ // Make sure that lto_get is an executable.
+
+ if (-1 == lstat(lto_get, &st))
+ {
+
+ printf("lto_util: lstat(%s) Error %d %s\n",
+ lto_get, errno, strerror(errno));
+ return 1;
+ }
+
+ if (!(st.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)))
+ {
+ printf("lto_util: \"%s\" %x mode & %x execute = %x not executable\n",
+ lto_get, st.st_mode,
+ S_IXOTH | S_IXGRP | S_IXUSR,
+ st.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR));
+ return 1;
+ }
+
+ if (err)
+ {
+ printf("pipe() err %d %s\n", errno, strerror(errno));
+ return 1;
+ }
+
+ pid = fork();
+ if (pid) // we're the parent - wait for the child.
+ {
+ pid_t x;
+
+ close(fd[1]); // close the write side
+
+ err = read_output(fd[0]);
+ x = waitpid(pid, 0, 0);
+ if (x != pid)
+ {
+ printf("%d = waitpid(%d) err %d %s\n",
+ x, pid, errno, strerror(errno));
+ }
+ }
+ else
+ {
+ int fd1;
+ int fd2;
+ // we're the child - exec the program.
+
+ // close(0); // close stdin
+ close(1); // close stdout
+ close(fd[0]); // close the write side
+
+ fd1 = dup(fd[1]); // reopen stdout and stderr
+ if (fd1 != 1)
+ {
+ fprintf(stderr,"<err>=failed to reopen stdout %d %s\n",
+ errno, strerror(errno));
+ return 3;
+ }
+
+ close(2); // close stderr
+ fd2 = dup(fd[1]); // to point to our pipe.
+ if (fd2 != 2)
+ {
+ printf("<err>=failed to reopen stderr %d %s\n",
+ errno, strerror(errno));
+ return 3;
+ }
+
+ printf("<progress>=Z\n"); // indicate we're alive
+
+ err = execl(lto_get, lto_get, url, file, "+DEBUG", 0);
+ printf("<err>=\"execl(%s,%s,%s,%s) error %d %s\"\n",
+ lto_get, url, file, debug,
+ errno, strerror(errno));
+ return 3;
+ }
+}
+
+static int
+parse_output(const char* buf)
+{
+ // printf("parse_output(%s) %d\n", buf, strlen(buf));
+ if (!strncmp(buf, "<done>=", 7))
+ {
+ int n;
+
+ sscanf(buf + 7, "%d", &n);
+ printf("done - %d bytes\n", n);
+ return 0;
+ }
+
+ if (!strncmp(buf, "<percent>=", 10))
+ {
+ int n;
+
+ sscanf(buf + 10, "%d", &n);
+ printf("percent = %d%%\n", n);
+ return -1;
+ }
+
+ if (!strncmp(buf, "<progress>=", 11))
+ {
+ char progress = buf[11];
+ printf("progress = '%c'\n", progress);
+ return -2;
+ }
+
+ if (!strncmp(buf, "<err>=", 6))
+ {
+ const char* err = buf + 6;
+ printf("error = %s\n", err);
+ return 1;
+ }
+
+ if (!strncmp(buf, "<debug>=", 8))
+ {
+ const char* dbg = buf + 8;
+ printf("debug = %s\n", dbg);
+ return -3;
+ }
+
+ printf("Unparsed output \"%s\"\n", buf);
+ return 2;
+}
+
+static int
+read_output(int fd)
+{
+ int offset = 0;
+ while (1)
+ {
+ char* p;
+ char* pNext;
+ char buf[1024];
+ int n = read(fd, buf + offset, sizeof(buf) - offset);
+ int err;
+ if (n < 0)
+ {
+ printf("read(%d) error %d %s\n", n, errno, strerror(errno));
+ return 2;
+ }
+ else if (n > 0)
+ {
+ buf[n] = 0;
+ // printf("read(%d,%d,%s)\n", fd, n, buf);
+ }
+ buf[n] = 0;
+
+ for (p = buf; p < buf + n; p = pNext + 1)
+ {
+ pNext = strchr(p, '\n');
+ if (!pNext)
+ {
+ pNext = buf+n;
+ offset = pNext - p;
+ memcpy(buf, p, offset);
+ buf[offset] = 0;
+ // printf("Offset %d\n", offset);
+ break;
+ }
+ *pNext = 0;
+ err = parse_output(p);
+
+ if (err >= 0)
+ {
+ return err;
+ }
+ }
+ }
+}
Added: developers/olv/openmoko-agpsui2/po/Makefile.in.in
===================================================================
--- developers/olv/openmoko-agpsui2/po/Makefile.in.in 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/po/Makefile.in.in 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,271 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper at gnu.ai.mit.edu>
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+#
+# - Modified by Owen Taylor <otaylor at redhat.com> to use GETTEXT_PACKAGE
+# instead of PACKAGE and to look for po2tbl in ./ not in intl/
+#
+# - Modified by jacob berkman <jacob at ximian.com> to install
+# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize
+
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+ at SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+datadir = @datadir@
+libdir = @libdir@
+localedir = $(libdir)/locale
+gnulocaledir = $(datadir)/locale
+gettextsrcdir = $(datadir)/glib-2.0/gettext/po
+subdir = po
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@
+
+CC = @CC@
+GENCAT = @GENCAT@
+GMSGFMT = @GMSGFMT@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+XGETTEXT = @XGETTEXT@
+MSGMERGE = msgmerge
+
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+
+INCLUDES = -I.. -I$(top_srcdir)/intl
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+SOURCES =
+POFILES = @POFILES@
+GMOFILES = @GMOFILES@
+DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \
+$(POFILES) $(GMOFILES) $(SOURCES)
+
+POTFILES = \
+
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+INSTOBJEXT = @INSTOBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
+
+.c.o:
+ $(COMPILE) $<
+
+.po.pox:
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ $(MSGMERGE) $< $(srcdir)/$(GETTEXT_PACKAGE).pot -o $*.pox
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+.po.gmo:
+ file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
+ && rm -f $$file && $(GMSGFMT) $(MSGFMT_OPTS) -o $$file $<
+
+.po.cat:
+ sed -f ../intl/po2msg.sed < $< > $*.msg \
+ && rm -f $@ && $(GENCAT) $@ $*.msg
+
+
+all: all- at USE_NLS@
+
+all-yes: $(CATALOGS)
+all-no:
+
+$(srcdir)/$(GETTEXT_PACKAGE).pot: $(POTFILES)
+ $(XGETTEXT) --default-domain=$(GETTEXT_PACKAGE) --directory=$(top_srcdir) \
+ --add-comments --keyword=_ --keyword=N_ \
+ --flag=g_strdup_printf:1:c-format \
+ --flag=g_string_printf:2:c-format \
+ --flag=g_string_append_printf:2:c-format \
+ --flag=g_error_new:3:c-format \
+ --flag=g_set_error:4:c-format \
+ --flag=g_markup_printf_escaped:1:c-format \
+ --flag=g_log:3:c-format \
+ --flag=g_print:1:c-format \
+ --flag=g_printerr:1:c-format \
+ --flag=g_printf:1:c-format \
+ --flag=g_fprintf:2:c-format \
+ --flag=g_sprintf:2:c-format \
+ --flag=g_snprintf:3:c-format \
+ --flag=g_scanner_error:2:c-format \
+ --flag=g_scanner_warn:2:c-format \
+ --files-from=$(srcdir)/POTFILES.in \
+ && test ! -f $(GETTEXT_PACKAGE).po \
+ || ( rm -f $(srcdir)/$(GETTEXT_PACKAGE).pot \
+ && mv $(GETTEXT_PACKAGE).po $(srcdir)/$(GETTEXT_PACKAGE).pot )
+
+install: install-exec install-data
+install-exec:
+install-data: install-data- at USE_NLS@
+install-data-no: all
+install-data-yes: all
+ if test -r "$(MKINSTALLDIRS)"; then \
+ $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \
+ else \
+ $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \
+ fi
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ case "$$cat" in \
+ *.gmo) destdir=$(gnulocaledir);; \
+ *) destdir=$(localedir);; \
+ esac; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \
+ if test -r "$(MKINSTALLDIRS)"; then \
+ $(MKINSTALLDIRS) $$dir; \
+ else \
+ $(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \
+ fi; \
+ if test -r $$cat; then \
+ $(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
+ echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \
+ else \
+ $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
+ echo "installing $(srcdir)/$$cat as" \
+ "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \
+ fi; \
+ if test -r $$cat.m; then \
+ $(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
+ echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \
+ else \
+ if test -r $(srcdir)/$$cat.m ; then \
+ $(INSTALL_DATA) $(srcdir)/$$cat.m \
+ $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
+ echo "installing $(srcdir)/$$cat as" \
+ "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \
+ else \
+ true; \
+ fi; \
+ fi; \
+ done
+ if test "$(PACKAGE)" = "glib"; then \
+ if test -r "$(MKINSTALLDIRS)"; then \
+ $(MKINSTALLDIRS) $(DESTDIR)$(gettextsrcdir); \
+ else \
+ $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(gettextsrcdir); \
+ fi; \
+ $(INSTALL_DATA) $(srcdir)/Makefile.in.in \
+ $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
+ else \
+ : ; \
+ fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+ catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
+ rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
+ rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
+ rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
+ done
+ if test "$(PACKAGE)" = "glib"; then \
+ rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
+ fi
+
+check: all
+
+dvi info tags TAGS ID:
+
+mostlyclean:
+ rm -f core core.* *.pox $(GETTEXT_PACKAGE).po *.old.po cat-id-tbl.tmp
+ rm -fr *.o
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f $(GMOFILES)
+
+distdir = ../$(GETTEXT_PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: update-po $(DISTFILES)
+ dists="$(DISTFILES)"; \
+ for file in $$dists; do \
+ ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+ || cp -p $(srcdir)/$$file $(distdir); \
+ done
+
+update-po: Makefile
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ tmpdir=`pwd`; \
+ cd $(srcdir); \
+ catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ echo "$$lang:"; \
+ if $(MSGMERGE) $$lang.po $(GETTEXT_PACKAGE).pot -o $$tmpdir/$$lang.new.po; then \
+ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
+ rm -f $$tmpdir/$$lang.new.po; \
+ else \
+ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
+ :; \
+ else \
+ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ exit 1; \
+ fi; \
+ fi; \
+ else \
+ echo "msgmerge for $$cat failed!"; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ fi; \
+ done
+
+# POTFILES is created from POTFILES.in by stripping comments, empty lines
+# and Intltool tags (enclosed in square brackets), and appending a full
+# relative path to them
+POTFILES: POTFILES.in
+ ( if test 'x$(srcdir)' != 'x.'; then \
+ posrcprefix='$(top_srcdir)/'; \
+ else \
+ posrcprefix="../"; \
+ fi; \
+ rm -f $@-t $@ \
+ && (sed -e '/^#/d' \
+ -e "s/^\[.*\] +//" \
+ -e '/^[ ]*$$/d' \
+ -e "s at .*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
+ | sed -e '$$s/\\$$//') > $@-t \
+ && chmod a-w $@-t \
+ && mv $@-t $@ )
+
+Makefile: Makefile.in.in ../config.status POTFILES
+ cd .. \
+ && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
+ $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Added: developers/olv/openmoko-agpsui2/po/POTFILES.in
===================================================================
Added: developers/olv/openmoko-agpsui2/src/Makefile.am
===================================================================
--- developers/olv/openmoko-agpsui2/src/Makefile.am 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/Makefile.am 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,30 @@
+localedir = $(datadir)/locale
+
+AM_CPPFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" -DLOCALEDIR=\"$(localedir)\"
+AM_CFLAGS = @OPENMOKO_CFLAGS@ -Wall
+AM_CXXFLAGS = @OPENMOKO_CFLAGS@ -Wall
+
+bin_PROGRAMS = openmoko-agpsui2
+
+openmoko_agpsui2_SOURCES = \
+ lto_download.cpp \
+ main.cpp \
+ notebook.cpp \
+ page_AZ.cpp \
+ page_main.cpp \
+ page_speed.cpp \
+ page_stats.cpp \
+ pm_agps.cpp \
+ gllin.cpp \
+ nmea.cpp \
+ page_add.cpp \
+ page_LTO.cpp \
+ page_map.cpp \
+ page_SS.cpp \
+ page_stress.cpp \
+ page_log.cpp \
+ pm_controls.cpp
+
+# :-(
+openmoko_agpsui2_LDADD = -L. -lrt
+
Added: developers/olv/openmoko-agpsui2/src/agps.h
===================================================================
--- developers/olv/openmoko-agpsui2/src/agps.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/agps.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef AGPS_H_
+#define AGPS_H_
+
+#ifndef AGPS_H_
+#include "agps.h"
+#endif
+
+#ifndef NMEA_H_
+#include "nmea.h"
+#endif
+
+#include <gtk/gtk.h>
+
+#if 1
+#define DEBUG_LV1
+#endif
+
+#if 0
+#define DEBUG_LV2
+#endif
+
+#if 0
+#define DEBUG_LV3
+#endif
+
+#if 0
+#define DEBUG_LV4
+#endif
+
+#if 0
+#define DEBUG_LV5
+#endif
+
+#if 0
+#define DEBUG_LV6
+#endif
+
+// void agps_start(GtkWidget* label);
+// void agps_stop(void);
+
+#endif
Added: developers/olv/openmoko-agpsui2/src/gllin.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/gllin.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/gllin.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,577 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* $Id: gllin.c $
+ *
+ * Global Locate driver for FIC GTA01 (OpenMoko Neo1973).
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <termios.h>
+#include <time.h>
+#include <stdio.h>
+#include <wait.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+typedef struct glData
+{
+ int pid;
+ int fd;
+} glData;
+
+static glData GL_DATA =
+{
+ 0, // pid
+ -1 // fd
+};
+
+#define pipeName "/dev/ttySAC1"
+
+extern const char* gllin_stop();
+static void gllin_poweron(int on);
+extern void gllin_arg_set(int arg_max, int* pArgc, const char** pp_argv);
+extern void trace_arg(int argc, char** argv);
+extern void pm_controls_active(bool active);
+extern void runtime_init();
+
+extern int debug_all;
+
+//------------------------------------------------------------------------------------
+//
+// isRunning()
+//
+//------------------------------------------------------------------------------------
+
+static int isRunning()
+{
+ // printf("isRunning pid %d fd %d\n", GL_DATA.pid, GL_DATA.fd);
+
+ // if (GL_DATA.pid && (-1 != GL_DATA.fd))
+ if ((-1 != GL_DATA.fd))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+//
+// gllin_conf_read()
+//
+//------------------------------------------------------------------------------------
+
+#define MAX_ARGS 20
+extern int nmea_log;
+int daemonize;
+
+static void gllin_conf_read(char* path, int* pArgc, char** argv)
+{
+ static char buf[4000];
+
+ memset(buf, 0, sizeof(buf));
+
+ int f = open("/etc/gllin/gllin.conf", O_RDONLY);
+ int n = read(f, buf, sizeof(buf) - 1);
+ char* p = buf;
+ char* pEnd;
+ int argc = 0;
+ int argMax = 0;
+ int dummy;
+ int skip_next_arg = 0;
+ daemonize = 0;
+
+ buf[sizeof(buf)-1] = 0;
+ if (n > 0) n = strlen(buf);
+
+ if (argv)
+ {
+ argv[0] = 0;
+ }
+
+ if (pArgc)
+ {
+ argMax = *pArgc - 1;
+ }
+ else
+ {
+ pArgc = &dummy;
+ }
+ *pArgc = 0;
+
+ close(f);
+
+ if (n <= 0)
+ {
+ strcpy(path, "./gllin");
+ *pArgc = 0;
+#ifdef DEBUG_LV1
+ printf("gllin conf[0] %s\n", path);
+#endif
+ printf("%s/%d path %s\n", __FILE__, __LINE__, path);
+ return;
+ }
+
+ // Get the path.
+ {
+ char* s = path;
+ strncpy(s, p, PATH_MAX);
+ s[PATH_MAX-1] = 0;
+
+ while ((*s != ' ') && *s)
+ {
+ ++s;
+ }
+ if (*s == ' ')
+ {
+ *s = 0;
+ p += (s - path);
+ }
+ }
+
+ // Split the config string into arguments.
+
+ if (argv) argv[argc++] = path;
+
+ for (pEnd = p + strlen(p); (argc < argMax) && (p < pEnd); ++p )
+ {
+ char* arg;
+ if (' ' == *p)
+ {
+ *p = 0;
+ continue;
+ }
+ if (!*p)
+ {
+ continue;
+ }
+
+ if (argv) argv[argc] = p;
+ do
+ {
+ ++p;
+ } while ((*p != ' ') && (*p != '\n') && (*p != '\r') && *p);
+ *p = 0;
+
+ ++argc;
+ arg = argv[argc-1];
+ if (!nmea_log)
+ {
+ if (skip_next_arg)
+ {
+ argv[--argc] = 0;
+ skip_next_arg = 0;
+ }
+ else if (strstr(arg, "log"))
+ {
+ argv[--argc] = 0;
+ skip_next_arg = 1;
+ }
+ }
+ if (!strcmp(arg, "+daemon"))
+ {
+ daemonize = 1;
+ }
+ }
+
+ if (argv)
+ {
+ argv[argc] = 0;
+ }
+ *pArgc = argc;
+}
+
+//------------------------------------------------------------------------------------
+//
+// gllin_detect()
+//
+// 1) Does the /etc/gllin/gllin.conf file exist?
+// 2) If so, parse the command line. Does the executable exist?
+// 3) If not, parse the default command line. Does THAT executable exist?
+//
+//------------------------------------------------------------------------------------
+
+const char* gllin_detect(void)
+{
+ struct stat st;
+ char path[PATH_MAX];
+
+ return NULL;
+
+ if (isRunning())
+ {
+ return 0;
+ }
+
+ mkfifo(pipeName, O_CREAT | O_EXCL);
+ chmod(pipeName, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH);
+
+ gllin_conf_read(path, 0, 0);
+
+ if (-1 == lstat(path, &st))
+ {
+ //int err = errno; /* UNUSED */
+ //char* sErr = strerror(errno); /* UNUSED */
+
+ // printf("gllin: lstat(%s) Error %d %s\n", path, err, sErr);
+ return "executable not found";
+ }
+
+ if (st.st_mode & S_IXOTH)
+ {
+#ifdef DEBUG_LV1
+ printf("gllin: gllin_detect OK %d\n",st.st_mode);
+#endif
+ return 0;
+ }
+
+#ifdef DEBUG_LV1
+ printf("gllin: gllin_detect FAIL %d\n",st.st_mode);
+#endif
+ return "gllin not executable";
+}
+
+//------------------------------------------------------------------------------
+//
+// gllin_fork()
+//
+// Fork and exec the GLLIN.
+//
+//------------------------------------------------------------------------------
+
+static void
+gllin_fork()
+{
+ int argc = MAX_ARGS;
+ char path[PATH_MAX];
+ char* argv[MAX_ARGS+1];
+ char** pargv = argv;
+ int rc = 0;
+
+ gllin_poweron(1);
+ return;
+
+ gllin_conf_read(path, &argc, pargv);
+ gllin_arg_set (MAX_ARGS, &argc, const_cast<const char**> (argv));
+ trace_arg(argc, argv);
+
+ pm_controls_active(false); // Turn off the main controls
+ runtime_init();
+
+ GL_DATA.pid = fork();
+ if (!GL_DATA.pid)
+ {
+ close(GL_DATA.fd);
+ GL_DATA.fd = -1;
+ rc = execvp(path, argv);
+ exit(2);
+ }
+ if (daemonize)
+ {
+ int stat;
+ waitpid(GL_DATA.pid, &stat, 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+//
+// gllin_start()
+//
+//------------------------------------------------------------------------------
+
+#define DEFAULT_GLLIN_WD "/tmp"
+
+int gllin_fd(void)
+{
+ return GL_DATA.fd;
+}
+
+static int gllin_uart_speed(void)
+{
+ int ret;
+ struct termios ti;
+
+ ret = tcgetattr(GL_DATA.fd, &ti);
+ if (ret<0)
+ return ret;
+
+ ret = cfsetispeed(&ti, B0);
+ if (ret < 0)
+ return ret;
+
+ ret = cfsetospeed(&ti, B9600);
+ if (ret < 0)
+ return ret;
+
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_lflag &= ~ICANON;
+ ti.c_lflag &= ~ECHO;
+
+ return tcsetattr(GL_DATA.fd, TCSANOW, &ti);
+}
+
+const char* gllin_start(void)
+{
+ int running = isRunning();
+ if (running)
+ {
+ return 0;
+ }
+
+ gllin_stop();
+
+ GL_DATA.fd = open(pipeName, O_RDWR);
+ if (gllin_uart_speed() < 0)
+ return "Fail to set speed";
+
+#ifdef DEBUG_LV1
+ printf("gllin_start open(%s) error %s\n",
+ pipeName, strerror(errno));
+#endif
+ if (-1 == GL_DATA.fd)
+ {
+ return "Can't open /tmp/nmeaNP";
+ }
+
+ const char* gllin_wd = getenv("GLLIN_WD");
+ if (!gllin_wd) gllin_wd = DEFAULT_GLLIN_WD;
+ if (chdir(gllin_wd))
+ {
+ return "Can't reach GLLIN_WD";
+ }
+
+ gllin_fork();
+
+ printf("gllin_start pid %d fd %d\n", GL_DATA.pid, GL_DATA.fd);
+
+ if (isRunning()) return 0;
+ return "Failed to start gllin";
+}
+
+//------------------------------------------------------------------------------
+//
+// gllin_stop()
+//
+//------------------------------------------------------------------------------
+
+extern void page_main_stop(const char* msg);
+
+const char* gllin_stop(void)
+{
+ page_main_stop(0);
+ pm_controls_active(true); // Turn ON the main controls
+ close(GL_DATA.fd);
+ GL_DATA.fd = -1;
+ gllin_poweron(0);
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+//
+// gta02
+//
+//------------------------------------------------------------------------------
+
+static ssize_t bwrite(int fd, const void *buf, size_t count, int delay)
+{
+ size_t i;
+
+ if (delay)
+ {
+ for (i = 0; i < count; i++)
+ {
+ if (write(fd, (unsigned char *) buf + i, 1) != 1)
+ return -1;
+ usleep(delay * 1000);
+ }
+ }
+ else
+ return write(fd, (unsigned char *) buf, count);
+
+ return i;
+}
+
+static void gllin_ubx(char cls, char id, const unsigned char *ubx, int size, int delay)
+{
+ unsigned char header[6], checksum[2];
+ int i;
+
+ if (!GL_DATA.fd)
+ return;
+
+ header[0] = 0xb5;
+ header[1] = 0x62;
+ header[2] = cls;
+ header[3] = id;
+ header[4] = size & 0xff;
+ header[5] = (size >> 8) & 0xff;
+
+ checksum[0] = checksum[1] = 0;
+ for (i = 2; i < 6; i++)
+ {
+ checksum[0] += header[i];
+ checksum[1] += checksum[0];
+ }
+
+ for (i = 0; i < size; i++)
+ {
+ checksum[0] += ubx[i];
+ checksum[1] += checksum[0];
+ }
+
+ if (bwrite(GL_DATA.fd, header, 6, delay) != 6)
+ goto fail;
+
+ if (size)
+ {
+ if (bwrite(GL_DATA.fd, (void *) ubx, size, delay) != size)
+ goto fail;
+ }
+
+ if (bwrite(GL_DATA.fd, checksum, 2, delay) != 2)
+ goto fail;
+
+ if (debug_all)
+ {
+ printf("ubx sent: ");
+ for (i = 0; i < 6; i++)
+ printf("%02x ", header[i]);
+ if (size)
+ {
+ for (i = 0; i < size; i++)
+ printf("%02x ", ubx[i]);
+ }
+
+ printf("%02x %02x\n", checksum[0], checksum[1]);
+ }
+
+ return;
+
+fail:
+ printf("ubx failed\n");
+}
+
+#if 0
+static void gllin_nmea(const char *nmea)
+{
+ char buf[1024];
+ const char *p = nmea;
+ int n, checksum = 0;
+
+ if (!GL_DATA.fd)
+ return;
+
+ while (*p)
+ checksum ^= *p++;
+
+ n = snprintf(buf, 256, "$%s*%02x\r\n", nmea, checksum);
+
+ if (bwrite(GL_DATA.fd, nmea, n, 0) != n)
+ printf("nmea failed\n");
+
+ printf("sent: %d: %s", n, buf);
+}
+
+static void gllin_poll_status(void)
+{
+ unsigned char buf[] = { 0x01, 0x03, 0x1 };
+
+ gllin_ubx(0x06, 0x01, buf, sizeof(buf), 4);
+}
+#endif
+
+static void gllin_poweron(int on)
+{
+ int fd;
+ char cmd;
+
+ fd = open("/sys/devices/platform/gta02-pm-gps.0/power_on", O_WRONLY);
+ if (!fd)
+ return;
+
+ cmd = (on) ? '1' : '0';
+
+ write(fd, &cmd, 1);
+
+ close(fd);
+
+ sleep(1);
+
+ /* initialize */
+ if (on)
+ {
+ //gllin_poll_status();
+ runtime_init();
+ }
+}
+
+void gllin_reset(char c)
+{
+ unsigned char ubx[4];
+ int bbr;
+
+ switch (c)
+ {
+ case 'c':
+ bbr = 0x7ff;
+ break;
+ case 'w':
+ bbr = 0x1;
+ break;
+ case 'h':
+ bbr = 0x0;
+ break;
+ }
+
+ ubx[0] = bbr & 0xff;
+ ubx[1] = (bbr >> 8) & 0xff;
+ ubx[2] = 0x8; /* stop GPS */
+ ubx[3] = 0x0;
+
+ gllin_ubx(0x06, 0x04, ubx, 4, 4);
+
+ sleep(2);
+
+ ubx[2] = 0x9; /* start GPS */
+ gllin_ubx(0x06, 0x04, ubx, 4, 4);
+
+ runtime_init();
+}
Added: developers/olv/openmoko-agpsui2/src/liblto.h
===================================================================
--- developers/olv/openmoko-agpsui2/src/liblto.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/liblto.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef LIB_LTO_H__
+#define LIB_LTO_H__ // {
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// liblto.h
+//
+
+//-----------------------------------------------------------------------------------
+//
+// Apply Aiding to the GLL
+//
+//-----------------------------------------------------------------------------------
+
+const char* ltoGetAiding(const char *lto_file_name);
+
+//-----------------------------------------------------------------------------------
+//
+// Given an LTO file, check the expiration:
+//
+// Parameters:
+// [input] lto_file_name
+// [output] *hours Filled with a positive number if LTO is good.
+// Negative number if LTO is expired.
+// [output] userMessage Pointer to formatted string that is filled with
+// a description of LTO validity.
+// [input] buf_size Size of the user message buffer.
+//
+// Returns:
+// const char* errmsg:
+// If 0, then there was no error.
+// If non-zero, then the LTO is not valid or readable for
+// the reason described in the string.
+// For error return cases, the hours might be filled in
+// with the hours since expiration or the hours until the
+// LTO becomes valid.
+//
+//-----------------------------------------------------------------------------------
+
+const char* ltoGetExpiration(const char *lto_file_name,
+ int* hours,
+ char* userMessage,
+ unsigned long buf_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIB_LTO_H__ // }
Added: developers/olv/openmoko-agpsui2/src/lto_download.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/lto_download.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/lto_download.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,472 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "lto_download.h"
+#include "liblto.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <memory.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <gtk/gtk.h>
+
+// See page_LTO.cpp for these:
+extern void lto_download_error(const char* msg);
+extern void lto_download_progress(char progress);
+extern void lto_download_percent(int n);
+extern void lto_download_done(void);
+
+static gint lto_cb_tag = 0;
+static int lto_fd = -1;
+static int lto_pid = 0;
+static bool lto_downloading_flag = false;
+
+static void lto_wait_for_stop(void);
+static void lto_fd_read(gpointer data, gint source, GdkInputCondition cond);
+static int lto_read_output(void);
+static const char* ltoDownloadPidWait();
+static void lto_read_init();
+
+const char* cc_lto_get = "/home/root/gpsd/lto_get";
+// st char* cc_url = "http://66.35.236.20" "/7day/v2/latest/lto2.dat";
+const char* cc_url = "http://gllto.glpals.com/7day/v2/latest/lto2.dat";
+const char* cc_file = "/home/root/gpsd/lto2.dat";
+
+//-----------------------------------------------------------------------------------
+//
+// ltoRemove()
+//
+//-----------------------------------------------------------------------------------
+
+const char*
+ltoRemove()
+{
+ int err = unlink(cc_file);
+ if (-1 == err)
+ {
+ return strerror(errno);
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------
+//
+// ltoLastDownloaded()
+//
+//-----------------------------------------------------------------------------------
+
+int
+ltoLastLoaded(int n, char* msg)
+{
+ struct stat lto_stat;
+ if (-1 == stat(cc_file, <o_stat))
+ {
+ return sprintf(msg, "Can't find %s", cc_file);
+ }
+
+ struct tm* p = localtime(<o_stat.st_mtime);
+ return strftime(msg, n, "LTO last loaded %x %X", p);
+}
+
+//------------------------------------------------------------------------------------
+//
+// ltoDownloadStart()
+//
+//------------------------------------------------------------------------------------
+
+const char*
+ltoDownloadStart()
+{
+ if (lto_downloading_flag)
+ {
+ return "Download in progress";
+ }
+ lto_read_init();
+
+ const char* lto_get = cc_lto_get;
+ const char* url = cc_url;
+ const char* file = cc_file;
+ const char* debug = "+DEBUG";
+ // const char* sim = "+SIM";
+ const char* sim = 0;
+
+#if 1
+ printf("ltoDownloadStart()/%d URL %s FILE %s PROGRAM %s %s\n",
+ __LINE__, url, file, lto_get, debug);
+#endif
+
+ // Make sure that lto_get is an executable.
+
+ struct stat st;
+ if (-1 == lstat(lto_get, &st))
+ {
+ fprintf(stderr, "omgui: lstat(%s) Error %d %s\n",
+ lto_get, errno, strerror(errno));
+ return "Can't find lto_get program";
+ }
+
+ if (!(st.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)))
+ {
+ fprintf(stderr, "omgui: \"%s\" mode %o not executable\n",
+ lto_get, st.st_mode);
+ return "lto_program is not executable";
+ }
+
+ int fd[2];
+ int err = pipe(fd);
+ if (err)
+ {
+ fprintf(stderr, "omgui: pipe() err %d %s\n", errno, strerror(errno));
+ return "Can't open pipe";
+ }
+
+ int pid = fork();
+ if (pid)
+ {
+ //--------------------------------------------------
+ // We're the parent - connect child output
+ // to GTK+ and then wait for input.
+ //--------------------------------------------------
+
+ close(fd[1]); // close the write side
+ lto_fd = fd[0];
+ lto_pid = pid;
+ lto_cb_tag = gdk_input_add(lto_fd, GDK_INPUT_READ, lto_fd_read, 0);
+ return 0;
+ }
+
+ //--------------------------------------------------
+ // we're the child - exec the program.
+ //--------------------------------------------------
+
+#if 1
+ printf("<debug>=\"starting to execl(%s,%s,%s,%s,%s)\"\n",
+ lto_get, url, file, debug, sim);
+
+ int opt = fcntl(fd[1], F_GETFL, 0);
+ if (-1 == opt)
+ {
+ fprintf(stderr,"<err>=fcntl(%d,F_GETFL,0) error %d %s\"\n",
+ fd[1], errno, strerror(errno));
+ }
+ else
+ {
+ opt |= O_NONBLOCK;
+ opt = fcntl(fd[1], F_SETFL, opt);
+ if (-1 == opt)
+ {
+ fprintf(stderr,"<err>=fcntl(%d,F_SETFL,0x%x) error %d %s\"\n",
+ fd[1], opt, errno, strerror(errno));
+ }
+ }
+#endif
+
+ // close(0); // close stdin
+ close(1); // close stdout
+ close(fd[0]); // close the write side
+
+ int fd1 = dup(fd[1]); // reopen stdout and stderr
+ if (fd1 != 1)
+ {
+ fprintf(stderr,"<err>=failed to reopen stdout %d %s\n",
+ errno, strerror(errno));
+ exit(3);
+ }
+
+ close(2); // close stderr
+ int fd2 = dup(fd[1]); // to point to our pipe.
+ if (fd2 != 2)
+ {
+ fprintf(stderr, "<err>=failed to reopen stderr %d %s\n",
+ errno, strerror(errno));
+ exit(3);
+ }
+
+ printf("<progress>=a\n"); // indicate we're alive
+
+ err = execl(lto_get, lto_get, url, file, debug, sim, 0);
+ printf("<err>=\"execl(%s,%s,%s,%s,%s) error %d %s\"\n",
+ lto_get, url, file, debug, sim,
+ errno, strerror(errno));
+ exit(3);
+ return "fork() and exec() failed";
+}
+
+//-----------------------------------------------------------------------------
+//
+// lto_parse_output()
+//
+// Decode the lto_get process output.
+//
+// Returns:
+// 0 Done. Successfull.
+// n < 0 Normal progress report. Continue.
+// n > 0 Error code. Should stop.
+//
+//-----------------------------------------------------------------------------
+
+static int
+lto_parse_output(const char* buf)
+{
+ // printf("parse_output(%s) %d\n", buf, strlen(buf));
+ if (!strncmp(buf, "<done>=", 7))
+ {
+ int n;
+
+ sscanf(buf + 7, "%d", &n);
+ // printf("done - %d bytes\n", n);
+ return 0;
+ }
+
+ if (!strncmp(buf, "<percent>=", 10))
+ {
+ int n;
+
+ sscanf(buf + 10, "%d", &n);
+ // printf("percent = %d%%\n", n);
+ lto_download_percent(n);
+ return -1;
+ }
+
+ if (!strncmp(buf, "<progress>=", 11))
+ {
+ char progress = buf[11];
+ // printf("progress = '%c'\n", progress);
+ lto_download_progress(progress);
+ return -2;
+ }
+
+ if (!strncmp(buf, "<err>=", 6))
+ {
+ const char* err = buf + 6;
+ // printf("error = %s\n", err);
+ lto_download_error(err);
+ return 1;
+ }
+
+ if (!strncmp(buf, "<debug>=", 8))
+ {
+ const char* dbg = buf + 8;
+ printf("debug = %s\n", dbg);
+ return -3;
+ }
+
+ printf("Unparsed lto output \"%s\"\n", buf);
+ return 2;
+}
+
+//-----------------------------------------------------------------------------
+//
+// lto_read_output()
+//
+// Read output of the lto_get process.
+//
+// Returns:
+// 0 Done. Successfull.
+// n < 0 Normal progress report. Continue.
+// n > 0 Error code. Should stop.
+//
+//-----------------------------------------------------------------------------
+
+static int offset;
+static char buf[1024];
+
+static void
+lto_read_init()
+{
+ offset = 0;
+ buf[0] = 0;
+}
+
+static int
+lto_read_output(int fd)
+{
+ // printf("lto_read(%d,buf,%d)\n", fd, sizeof(buf) - offset);
+ int n = read(fd, buf + offset, sizeof(buf) - offset);
+ if (n < 0)
+ {
+ // printf("lto_read(%d) error %d %s\n", n, errno, strerror(errno));
+ return 2;
+ }
+ else if (n > 0)
+ {
+ buf[n] = 0;
+ // printf("lto_read(%d,%d,%s)\n", fd, n, buf);
+ }
+ else
+ {
+ // printf("read(%d,%d)\n", fd, n);
+ return -4;
+ }
+ char* pEnd = buf + n + offset;
+ *pEnd = 0;
+
+ char* pNext;
+ for (char* p = buf; p < pEnd; p = pNext + 1)
+ {
+ pNext = strchr(p, '\n');
+ if (!pNext)
+ {
+ pNext = pEnd;
+ offset = pNext - p; // printf("Offset %d\n", offset);
+ memcpy(buf, p, offset);
+ buf[offset] = 0;
+ break;
+ }
+ *pNext = 0;
+
+ int err = lto_parse_output(p);
+ if (err >= 0)
+ {
+ return err;
+ }
+ }
+ return -5; // Incomplete read.
+}
+
+static void
+lto_fd_read(gpointer data, gint source, GdkInputCondition cond)
+{
+ GtkWidget* label = GTK_WIDGET(data);
+ if (source != lto_fd)
+ {
+ lto_download_error("fd mismatch");
+ return;
+ }
+ if (GDK_INPUT_READ != cond)
+ {
+ lto_download_error("gtk read callback condition mismatch");
+ return;
+ }
+ int err = lto_read_output(lto_fd);
+
+ if (err >= 0)
+ {
+ // printf("omgui: lto_status %d\n", err);
+ // fflush(stdout);
+ lto_wait_for_stop();
+ }
+}
+
+//-----------------------------------------------------------------------------
+//
+// lto_download_stop()
+//
+// Disconnect the LTO_GET process from GTK+
+//
+//-----------------------------------------------------------------------------
+
+static void
+lto_wait_for_stop()
+{
+ const char* msg = ltoDownloadPidWait();
+ if (msg)
+ {
+ lto_download_error(msg);
+ if (lto_pid > 0)
+ {
+ printf("lto_wait_for_stop()/%d kill(%d,SIGKILL %d)\n",
+ __LINE__, lto_pid, SIGKILL);
+ kill(lto_pid, SIGKILL);
+ }
+ }
+ else
+ {
+ lto_download_error("LTO Download Done");
+ }
+ gdk_input_remove(lto_cb_tag);
+ close(lto_fd);
+ lto_fd = -1;
+}
+
+//-----------------------------------------------------------------------------
+//
+// lto_download_stop()
+//
+// Forcibly stop the LTO download.
+//
+//-----------------------------------------------------------------------------
+
+void
+lto_download_stop()
+{
+ if (lto_pid > 0)
+ {
+ printf("lto_download_stop()/%d kill(%d,SIGKILL %d)\n",
+ __LINE__, lto_pid, SIGKILL);
+ kill(lto_pid, SIGKILL);
+ lto_wait_for_stop();
+ }
+}
+
+//-----------------------------------------------------------------------------
+//
+// ltoDownloadPidWait()
+//
+// Wait for the LTO download PID to complete.
+//
+// Returns:
+// 0 Done. Successfull.
+// msg Some error message.
+//
+//-----------------------------------------------------------------------------
+
+static const char*
+ltoDownloadPidWait()
+{
+ int stat = 0;
+ pid_t x = waitpid(lto_pid, &stat, 0); // WNOHANG will poll
+ if (x == lto_pid)
+ {
+ lto_downloading_flag = false;
+ lto_pid = 0;
+ lto_download_done();
+ }
+ else
+ {
+ fprintf(stderr, "omgui: %d = waitpid(%d) err %d %s\n",
+ x, lto_pid, errno, strerror(errno));
+ }
+ if (WIFEXITED(stat))
+ {
+ lto_download_done();
+ lto_downloading_flag = false;
+ lto_pid = 0;
+
+ int exit_code = WEXITSTATUS(stat);
+ fprintf(stderr, "omgui: %s exit code %d\n",
+ cc_lto_get, exit_code);
+ if (exit_code) return "lto_get failed: abnormal exit";
+ return 0;
+ }
+ if (WIFSIGNALED(stat))
+ {
+ return "lto_get failed: signalled";
+ }
+ return "lto_get wait failed";
+}
Added: developers/olv/openmoko-agpsui2/src/lto_download.h
===================================================================
--- developers/olv/openmoko-agpsui2/src/lto_download.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/lto_download.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern const char* ltoRemove(void);
+extern int ltoExpires(int* days, int* hours);
+extern int ltoLastLoaded(int n, char* buf);
+extern const char* ltoDownloadStart();
Added: developers/olv/openmoko-agpsui2/src/main.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/main.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/main.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,152 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#include "agps.h"
+
+GtkWidget* notebook_create(GtkWidget* window);
+
+extern GtkLabel* agpsLabel;
+extern void NMEA_MSG(const char* msg);
+
+void
+button_on(GtkWidget *button, gboolean sensitive)
+{
+ gtk_widget_set_sensitive(button, sensitive);
+}
+
+void
+trace_arg(int argc, char** argv)
+{
+ FILE* f = fopen("omgui.trace", "a+");
+ int i = 0;
+
+ fprintf(f, "\nCommand: ");
+ for (; i < argc; ++i)
+ {
+ fprintf(f, "\"%s\" ", argv[i]);
+ printf( "%s ", argv[i]);
+ }
+ fprintf(f, "\n");
+ printf( "\n");
+ fclose(f);
+}
+
+void
+trace_env(char** envp)
+{
+ FILE* f = fopen("omgui.trace", "a+");
+ for (; *envp; ++envp)
+ {
+ fprintf(f, "env: \"%s\"\n", *envp);
+ }
+ fclose(f);
+}
+
+const char* argv0;
+
+FILE *dump_nmea_fp;
+static int dump_nmea;
+int debug_all;
+static GOptionEntry entries[] = {
+ { "debug-nmea", 'd', 0, G_OPTION_ARG_NONE, &dump_nmea, NULL, NULL },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &debug_all, NULL, NULL },
+ { NULL }
+};
+
+int main(int argc, char** argv, char** envp)
+{
+ GtkWidget* window;
+ GtkWidget* label;
+ GtkWidget* button1;
+ GtkWidget* button2;
+ GtkWidget* vbox;
+ GtkWidget* table;
+
+ argv0 = argv[0];
+
+ // printf("%s/%d\n", __FILE__, __LINE__);
+
+ // trace_arg(argc, argv);
+ // trace_env(envp);
+
+ if (!g_thread_supported())
+ {
+ g_thread_init(NULL);
+ }
+
+ gdk_threads_init();
+ gtk_init(&argc, &argv);
+
+ {
+ GOptionContext *context = g_option_context_new("gps");
+
+ g_option_context_add_main_entries(context, entries, NULL);
+ g_option_context_parse(context, &argc, &argv, NULL);
+ g_option_context_free(context);
+
+ if (debug_all)
+ dump_nmea_fp = stdout;
+
+ if (dump_nmea)
+ {
+ char name[128];
+ time_t t;
+ struct tm *tmp;
+ int fd;
+
+ if (g_chdir("/home/root") == 0)
+ {
+ strcpy(name, "nmea-");
+ t = time(NULL);
+ tmp = localtime(&t);
+
+ strftime(name + 5, sizeof(name) - 5, "%m%d-%H%M", tmp);
+
+ strcat(name, ".log");
+
+ fd = open(name, O_CREAT | O_WRONLY | O_SYNC);
+ if (fd >= 0)
+ dump_nmea_fp = fdopen(fd, "w");
+ }
+ }
+ }
+ //--------------------------------------------------------------------------
+ // top window
+ //--------------------------------------------------------------------------
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW (window), "AGPS Test Program");
+ gtk_window_set_default_size(GTK_WINDOW(window),480,640);
+ g_signal_connect(G_OBJECT(window), "delete_event", gtk_main_quit, NULL);
+
+ gtk_container_add(GTK_CONTAINER(window), notebook_create(window));
+
+ gtk_widget_show(window);
+
+ gdk_threads_enter();
+ gtk_main();
+ gdk_threads_leave();
+
+ return 0;
+}
Added: developers/olv/openmoko-agpsui2/src/nmea.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/nmea.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/nmea.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,321 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "nmea.h"
+
+static char delim[] = ",*";
+
+extern void page_SS_have_prn(int prn, int ss, int el, int az);
+extern void page_SS_use_prn (int prn);
+extern void page_SS_unuse_prns(void);
+extern void notebook_nmea_epoch(void);
+
+int GPGGA(char* str, struct nmea_gga* gga)
+{
+ char* ptr = str;
+ char* pptr;
+ int i = 0;
+ bool done = false;
+
+ // g_printf("GGA(\"%s\")\n", str);
+
+ for (ptr = str; !done && ptr; ++ptr)
+ {
+ for (pptr = ptr; *ptr!=delim[0] && *ptr!=delim[1]; ++ptr)
+ {
+ if (!*ptr)
+ {
+ done = true;
+ break;
+ }
+ }
+ *ptr = '\0';
+
+ switch(i)
+ {
+ default: break;
+ case 0: strncpy(gga->sentence, pptr, 8); ++i; break;
+ case 1: strncpy(gga->time, pptr, 16); ++i; break;
+ case 2: strncpy(gga->latitude, pptr, 16); ++i; break;
+ case 3: strncpy(gga->la, pptr, 4); ++i; break;
+ case 4: strncpy(gga->longitude, pptr, 16); ++i; break;
+ case 5: strncpy(gga->lo, pptr, 4); ++i; break;
+ case 6: strncpy(gga->fix_quality, pptr, 4); ++i; break;
+ case 7: strncpy(gga->nos, pptr, 4); ++i; break;
+ case 8: strncpy(gga->hdop, pptr, 8); ++i; break;
+ case 9: strncpy(gga->alme, pptr, 8); ++i; break;
+ case 10: strncpy(gga->al, pptr, 4); ++i; break;
+ case 11: strncpy(gga->hog, pptr, 8); ++i; break;
+ case 12: strncpy(gga->ho, pptr, 4); ++i; break;
+ case 13: strncpy(gga->tis, pptr, 16); ++i; break;
+ case 14: strncpy(gga->DGPS, pptr, 16); ++i; break;
+ case 15: strncpy(gga->checksum, pptr, 4); ++i; break;
+ }
+ }
+ // g_printf("%d gga->time(\"%s\")\n", __LINE__, gga->time);
+ return 0;
+}
+
+int GPGSV(char* str, struct nmea_gsv* gsv)
+{
+ char* ptr = str;
+ char* pptr;
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ bool done = false;
+ int checksum = 0;
+
+ // g_printf("\"%s\"", str);
+
+ for (ptr = str; !done && ptr; ++ptr)
+ {
+ for (pptr = ptr; *ptr!=delim[0] && *ptr!=delim[1]; ++ptr)
+ {
+ if (!*ptr)
+ {
+ done = true;
+ break;
+ }
+ }
+ *ptr = '\0';
+
+ if (*ptr == delim[1])
+ {
+ checksum = 1;
+ }
+
+ switch(i)
+ {
+ default: break;
+ case 0: strncpy(gsv->sentence, pptr, 8); ++i; break;
+ case 1: strncpy(gsv->nose, pptr, 4); ++i; break;
+ case 2: strncpy(gsv->sn, pptr, 4); ++i; break;
+ case 3: strncpy(gsv->nosa, pptr, 4); ++i; break;
+ case 5: strncpy(gsv->checksum, pptr, 4); ++i; break;
+
+ case 4: strncpy(gsv->sate[j][k], pptr, 4);
+ if (++k >= 4)
+ {
+ int prn = atoi(gsv->sate[j][0]);
+ int el = atoi(gsv->sate[j][1]);
+ int az = atoi(gsv->sate[j][2]);
+ int CN0 = atoi(gsv->sate[j][3]);
+
+ // printf("%d) %s %s %s %s\n",
+ // j,
+ // gsv->sate[j][0], gsv->sate[j][1],
+ // gsv->sate[j][2], gsv->sate[j][3]);
+ // printf("%d) prn %d el %d az %d ss %d\n",
+ // j, prn, el, az, CN0);
+ page_SS_have_prn(prn, CN0, el, az);
+
+ k = 0; // Start over with the
+ ++j; // ... next SV
+ }
+ if (checksum)
+ {
+ gsv->n = j;
+ i = 5;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int GPGSA(char* str, struct nmea_gsa* gsa)
+{
+ char* ptr;
+ char* pptr;
+ int i = 0;
+ int j = 0;
+ bool done = false;
+ page_SS_unuse_prns();
+
+ // g_printf("\"%s\"", str);
+
+ for (ptr = str; !done && ptr; ++ptr)
+ {
+ for (pptr = ptr; *ptr!=delim[0] && *ptr!=delim[1]; ++ptr)
+ {
+ if (!*ptr)
+ {
+ done = true;
+ break;
+ }
+ }
+ *ptr = '\0';
+
+ switch(i)
+ {
+ default: break;
+ case 0: strncpy(gsa->sentence, pptr, 8); ++i; break;
+ case 1: strncpy(gsa->AM, pptr, 4); ++i; break;
+ case 2: strncpy(gsa->mode, pptr, 4); ++i; break;
+ case 4: strncpy(gsa->PDOP, pptr, 8); ++i; break;
+ case 5: strncpy(gsa->HDOP, pptr, 8); ++i; break;
+ case 6: strncpy(gsa->VDOP, pptr, 8); ++i; break;
+ case 7: strncpy(gsa->checksum, pptr, 4); ++i; break;
+ case 3:
+ if (j < 12)
+ {
+ strncpy(gsa->id[j], pptr, 4);
+ j++;
+ }
+ else ++i;
+ break;
+ }
+ }
+
+ gsa->n = 0;
+ for (i = 0; i < 12; ++i)
+ {
+ if (strlen(gsa->id[i]))
+ {
+ page_SS_use_prn(atoi(gsa->id[i]));
+ ++gsa->n;
+ }
+ }
+ notebook_nmea_epoch();
+
+ return 0;
+}
+
+void page_stats_fix_time(float ttf, float ttff);
+
+int PGLOR_FIX(char* str, struct nmea_lor* lor)
+{
+ bool done = false;
+ int i = 0;
+
+ lor->fixTime = -1.0;
+ lor->ttff = -1.0;
+
+ char* pTTFF = strstr(str, ",TR,");
+ if (pTTFF && (1 != sscanf(pTTFF + 4, "%f", &lor->ttff)))
+ {
+ lor->ttff = -1.0;
+ }
+
+ for (char* ptr = str; !done && ptr; ++i, ++ptr)
+ {
+ char* pptr = ptr;
+ for (; *ptr != delim[0] && *ptr != delim[1]; ++ptr)
+ {
+ if (!*ptr)
+ {
+ done = true;
+ break;
+ }
+ }
+ *ptr = '\0';
+
+ if (2 == i) // Get the fix time.
+ {
+ if (1 != sscanf(pptr, "%f", &lor->fixTime))
+ {
+ lor->fixTime = -1.0;
+ }
+ }
+ }
+
+ // printf("PGLOR_FIX ttff %f ttf %f\n", lor->ttff, lor->fixTime);
+ page_stats_fix_time(lor->fixTime, lor->ttff);
+ return 0;
+}
+
+// Show integration problems with the platform
+// Skip the "$PGLOR,IGR," to collect the data up to "*"
+// Skip the "$PGLOR,IGC," to collect the data up to "*"
+
+int PGLOR_IGR(char* str, struct nmea_lor* lor)
+{
+ char* c = 0;
+ int ch = ' ';
+ if (strstr(str, ",IGR"))
+ {
+ ++lor->nIgr;
+ lor->igr[0] = 0;
+ }
+ c = strstr(str, "*");
+ if (c)
+ {
+ *c = 0;
+ }
+ str += 11; // Skip the "$PGLOR,IGR,"
+
+ // Replace ',' in the IGR messages by ' ' alternating with '='.
+ for (c = str; *c; ++c)
+ {
+ if (',' == *c)
+ {
+ *c = ch;
+ if (' ' == ch) ch = '=';
+ else ch = ' ';
+ }
+ if ('.' == *c) *c = 'x';
+ }
+
+ strcat(lor->igr, str);
+ strcat(lor->igr, "\n\r");
+ // printf("PGLOR_IGR/%d \"%s\"\n", __LINE__, lor->igr);
+ return 0;
+}
+
+// Get the firmware version number
+// Skip the "$PGLOR,RID," to collect the data up to "*"
+
+int PGLOR_RID(char* str, struct nmea_lor* lor)
+{
+ char* c = 0;
+ c = strstr(str, "*");
+ if (c) *c = 0; // Truncate the checksum "*XX\n\r"
+
+ str += 15; // Skip the "$PGLOR,RID,GLL,"
+
+ // Replace ',' in the message by '.'
+ for (c = str; *c; ++c)
+ {
+ if (',' == *c) *c = '.';
+ }
+ strcpy(lor->rid, str);
+ printf("PGLOR_RID/%d %s\n", __LINE__, lor->rid);
+ return 0;
+}
+
+// The GLLIN has exited.
+
+int PGLOR_EXIT(char* str, struct nmea_lor* lor)
+{
+ // lor->exit = 1;
+ printf("PGLOR_EXIT/%d\n", __LINE__);
+ return 0;
+}
+
+// TODO: Decode the RMC message.
+
+int GPRMC(char* str, struct nmea_rmc* rmc)
+{
+ return 0;
+}
Added: developers/olv/openmoko-agpsui2/src/nmea.h
===================================================================
--- developers/olv/openmoko-agpsui2/src/nmea.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/nmea.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef NMEA_H_
+#define NMEA_H_
+
+#ifndef NMEA_H_
+#include "nmea.h"
+#endif
+
+#define GGA "$GPGGA"
+#define RMC "$GPRMC"
+#define GSV "$GPGSV"
+#define GSA "$GPGSA"
+#define LOR "$PGLOR"
+
+struct nmea_gga {
+ char sentence[8];
+ char time[16];
+ char latitude[16];
+ char la[4];
+ char longitude[16];
+ char lo[4];
+ char fix_quality[4];
+ char nos[4];
+ char hdop[8];
+ char alme[8];
+ char al[4];
+ char hog[8];
+ char ho[4];
+ char tis[16];
+ char DGPS[16];
+ char checksum[4];
+};
+
+struct nmea_rmc {
+ char sentence[8];
+};
+
+struct nmea_gsv {
+ char sentence[8];
+ char nose[4];
+ char sn[4];
+ char nosa[4];
+ char sate[4][4][4];
+ char checksum[4];
+ int n;
+};
+
+struct nmea_gsa {
+ char sentence[8];
+ char AM[4];
+ char mode[4];
+ char id[12][4];
+ char PDOP[8];
+ char HDOP[8];
+ char VDOP[8];
+ char checksum[4];
+ int n;
+};
+
+struct nmea_lor {
+ int nIgr;
+ float fixTime;
+ float ttff;
+ char sentence[8];
+ char rid[32];
+ char igr[80*5];
+};
+
+int GPGGA(char* str, struct nmea_gga* gga);
+int GPGSV(char* str, struct nmea_gsv* gsv);
+int GPGSA(char* str, struct nmea_gsa* gsa);
+int GPRMC(char* str, struct nmea_rmc* rmc);
+int PGLOR_IGR(char* str, struct nmea_lor* lor);
+int PGLOR_RID(char* str, struct nmea_lor* lor);
+int PGLOR_FIX(char* str, struct nmea_lor* lor);
+int PGLOR_EXIT(char* str, struct nmea_lor* lor);
+
+#endif
Added: developers/olv/openmoko-agpsui2/src/notebook.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/notebook.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/notebook.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,451 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PAGE_LTO
+#define PAGE_MAP
+#define PAGE_GSM
+#define PAGE_STRESS
+// #define PAGE_ADD
+#define PAGE_RFI
+
+#ifndef PAGE_STRESS_H__ // {
+#include "page_stress.h"
+#endif // }
+
+extern const char* argv0;
+GtkWidget* page_main_create (GtkWidget* window);
+GtkWidget* page_SS_create (GtkWidget* window);
+GtkWidget* page_AZ_create (GtkWidget* window);
+GtkWidget* page_speed_create(GtkWidget* window);
+GtkWidget* page_stats_create(GtkWidget* window);
+GtkWidget* page_stress_create(GtkWidget* window);
+GtkWidget* page_LTO_create(GtkWidget* window);
+GtkWidget* page_MAP_create(GtkWidget* window);
+
+#ifdef PAGE_RFI
+GtkWidget* page_bt_create(GtkWidget* window);
+GtkWidget* page_audio_create(GtkWidget* window);
+GtkWidget* page_rfi_create(GtkWidget* window);
+#endif
+
+#ifdef PAGE_GSM
+GtkWidget* page_GSM_create(GtkWidget* window);
+#endif
+
+#ifdef PAGE_ADD
+GtkWidget* page_ADD_create(GtkWidget* window);
+#endif
+
+GtkWidget* page_log_create(GtkWidget* window);
+
+static GtkWidget* notebook = 0;
+
+static void
+on_notebook_3(GtkWidget *widget, gint arg1, gpointer data)
+{
+ // printf("%s/%d signal %s\n", __FILE__, __LINE__, (char*) data);
+}
+
+static void
+on_notebook_4(GtkWidget *widget, gint arg1, guint page_num, gpointer data)
+{
+ // printf("%s/%d signal %s page %d\n",
+ // __FILE__, __LINE__,
+ // (char*) data, page_num);
+}
+
+static void
+notebook_callback(int cb_i, const char* signal)
+{
+ GCallback cb = G_CALLBACK(on_notebook_3);
+ if (4 == cb_i) cb = G_CALLBACK(on_notebook_4);
+
+ g_signal_connect(G_OBJECT(notebook), signal, cb, (gpointer) signal);
+}
+
+// Bitmap for the pages to be created:
+
+enum
+{
+ ALLOW_MAIN = 0x01, // part of minimum
+ ALLOW_SS = 0x02, // part of minimum
+ ALLOW_AZ = 0x04, // part of minimum
+ ALLOW_SPEED = 0x08,
+ ALLOW_STATS = 0x10,
+ ALLOW_STRESS = 0x20,
+ ALLOW_LTO = 0x40, // part of minimum
+ ALLOW_MAP = 0x80, // part of minimum
+ ALLOW_ADD = 0x100,
+
+ ALLOW_MINIMUM = (ALLOW_MAP+ALLOW_MAIN+ALLOW_SS+ALLOW_AZ)
+};
+
+static int notebook_page_mask = 0;
+
+static const char*
+page_names[] =
+{
+ "main",
+ "signal strength",
+ "azimuth",
+ "dials",
+ "test",
+ "stats",
+ "LTO",
+ "plot"
+};
+
+#ifndef DIM
+#define DIM(x) (sizeof(x)/sizeof(*x))
+#endif
+
+static const char*
+notebook_page_name(int i)
+{
+ // printf("%s/%d notebook_page_name(%d) %d ",
+ // __FILE__, __LINE__, i, DIM(page_names));
+ if (i >= 0 && i < DIM(page_names))
+ {
+ // printf("%s\n", page_names[i]);
+ return page_names[i];
+ }
+ // printf(",<null>\n");
+ return 0;
+}
+
+GtkWidget*
+notebook_create(GtkWidget* window)
+{
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ notebook = gtk_notebook_new();
+ GtkWidget* label;
+ gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
+
+ int page_mask = 0;
+ int nPages = 0;
+
+ if (argv0 && *argv0)
+ {
+ const char key[] = {"-pagemask-"};
+ const char* p = strstr(argv0,key);
+ if (p)
+ {
+ p += strlen(key);
+ page_mask = strtol(p, 0, 16);
+ }
+ }
+ page_mask |= ALLOW_MINIMUM;
+ notebook_page_mask = page_mask;
+
+ if (page_mask & ALLOW_MAIN)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("run");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_main_create(window), label);
+ }
+
+ if (page_mask & ALLOW_SS)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("SS");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_SS_create(window), label);
+ }
+
+ if (page_mask & ALLOW_AZ)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("AZ");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_AZ_create(window), label);
+ }
+
+ if (page_mask & ALLOW_SPEED)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("dial");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_speed_create(window), label);
+ }
+
+ if (page_mask & ALLOW_STATS)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("stat");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_stats_create(window), label);
+ }
+
+#ifdef PAGE_LTO
+ if (page_mask & ALLOW_LTO)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("LTO");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_LTO_create(window), label);
+ }
+#endif
+
+#ifdef PAGE_MAP
+ if (page_mask & ALLOW_MAP)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_MAP_create(window),
+ gtk_label_new("plot") );
+ }
+#endif
+
+#ifdef PAGE_STRESS
+ if (page_mask & ALLOW_STRESS)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("test");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_stress_create(window), label);
+ }
+#endif
+
+#ifdef PAGE_ADD
+ if (page_mask & ALLOW_ADD)
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_ADD_create(window), gtk_label_new("ADD"));
+ }
+#endif
+
+ {
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ ++nPages;
+ label = gtk_label_new("Log");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ page_log_create(window), label);
+ }
+
+ if (nPages > 7)
+ {
+ gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
+
+ notebook_callback(3, "change-current-page");
+ notebook_callback(3, "focus-tab");
+ notebook_callback(3, "move-focus-out");
+// notebook_callback(4, "page-added"); // in GTK+ v2.10 and later
+// notebook_callback(4, "page-removed"); // in GTK+ v2.10 and later
+// notebook_callback(4, "page-reordered"); // in GTK+ v2.10 and later
+// notebook_callback(4, "reorder-tab"); // in GTK+ v2.10 and later
+ notebook_callback(3, "select-page");
+ notebook_callback(4, "switch-page");
+
+ }
+ gtk_widget_show(notebook);
+
+ // printf("%s/%d\n", __FILE__, __LINE__);
+ return notebook;
+}
+
+static bool b_exposedMN = false; // Main page
+static bool b_exposedSS = false; // Signal strength
+static bool b_exposedAZ = false; // Azimuth
+static bool b_exposedSP = false; // Speed
+static bool b_exposedST = false; // Stats
+static bool b_exposedRR = false; // Stress
+static bool b_exposedLT = false; // LTO
+static bool b_exposedMP = false; // Map
+
+bool exposedMN() { return b_exposedMN; }
+bool exposedSS() { return b_exposedSS; }
+bool exposedAZ() { return b_exposedAZ; }
+bool exposedSP() { return b_exposedSP; }
+bool exposedST() { return b_exposedST; }
+bool exposedRR() { return b_exposedRR; }
+bool exposedLT() { return b_exposedLT; }
+bool exposedMP() { return b_exposedMP; }
+
+extern void page_main_done();
+extern void page_SS_done();
+extern void page_AZ_done();
+extern void page_speed_done();
+extern void page_stats_done();
+extern void page_stress_done();
+extern void page_LTO_done();
+extern void page_MAP_done();
+
+void
+notebook_nmea_epoch(void)
+{
+#if 0
+ printf("notebook_nmea_epoch() %s%s%s%s%s\n",
+ (exposedMN()) ? "main" : "",
+ (exposedSS()) ? "SS" : "",
+ (exposedAZ()) ? "AZ" : "",
+ (exposedSP()) ? "speed" : "",
+ (exposedST()) ? "stats" : "",
+ (exposedST()) ? "LTO" : "",
+ (exposedMP()) ? "MAP" : "",
+ (exposedRR()) ? "stress" : "");
+#endif
+ if (exposedMN()) page_main_done();
+ if (exposedSS()) page_SS_done();
+ if (exposedAZ()) page_AZ_done();
+ if (exposedSP()) page_speed_done();
+ if (exposedST()) page_stats_done();
+ if (exposedRR()) page_stress_done();
+ if (exposedLT()) page_LTO_done();
+ if (exposedMP()) page_MAP_done();
+}
+
+void
+notebook_expose(const char* pageName)
+{
+ // printf("notebook_expose(%s)\n", pageName);
+ b_exposedMN = false;
+ b_exposedSS = false;
+ b_exposedAZ = false;
+ b_exposedSP = false;
+ b_exposedST = false;
+ b_exposedRR = false;
+ b_exposedLT = false;
+ if (!strcmp("MN", pageName)) b_exposedMN = true;
+ if (!strcmp("SS", pageName)) b_exposedSS = true;
+ if (!strcmp("AZ", pageName)) b_exposedAZ = true;
+ if (!strcmp("SP", pageName)) b_exposedSP = true;
+ if (!strcmp("ST", pageName)) b_exposedST = true;
+ if (!strcmp("RR", pageName)) b_exposedRR = true;
+ if (!strcmp("LT", pageName)) b_exposedLT = true;
+ if (!strcmp("MP", pageName)) b_exposedMP = true;
+}
+
+void
+notebook_report_header(FILE* f, const char* msg)
+{
+ fprintf(f,
+ "\n"
+ "\n"
+ " %s Page\n"
+ "-------------------------------------------------------------------\n",
+ msg);
+}
+#define HDR(m) notebook_report_header(f,m)
+
+const char* page_main_omgui_version(void);
+
+void
+notebook_report_header(FILE* f)
+{
+ time_t t = time(0);
+ fprintf(f,
+ "\n"
+ " %s Report\n"
+ " Date: %s\n"
+ "\n"
+ " Summary\n"
+ "-------------------------------------------------------------------\n"
+ "Pages enabled are %x:\n",
+
+ page_main_omgui_version(),
+ ctime(&t),
+ notebook_page_mask);
+
+ int page_count = 0;
+ for (int bit = 0; bit < 32; ++bit)
+ {
+ const char* page_name = notebook_page_name(bit);
+ if (page_name && ((1L << bit) & notebook_page_mask))
+ {
+ if (page_count > 3)
+ {
+ page_count = 0;
+ fprintf(f, ",\n");
+ }
+ fprintf(f, "%s %s",
+ (page_count) ? "," : "", page_name);
+ ++page_count;
+ }
+ }
+ if (page_count) fprintf(f, "\n");
+}
+
+void
+notebook_report_trailer(FILE* f)
+{
+}
+
+extern void page_main_report(FILE* f);
+extern void page_SS_report(FILE* f);
+extern void page_AZ_report(FILE* f);
+extern void page_speed_report(FILE* f);
+extern void page_stats_report(FILE* f);
+extern void page_stress_report(FILE* f);
+extern void page_LTO_report(FILE* f);
+extern void page_map_report(FILE* f);
+extern void page_RFI_report(FILE* f);
+extern void page_audio_report(FILE* f);
+extern void page_BT_report(FILE* f);
+extern void page_GSM_report(FILE* f);
+extern void page_ADD_report(FILE* f);
+
+void
+notebook_report(FILE* f)
+{
+ int page_mask = notebook_page_mask;
+ notebook_report_header(f);
+
+ if (page_mask & ALLOW_MAIN ) HDR("Main" ), page_main_report (f);
+ if (page_mask & ALLOW_SS ) HDR("Signal Strength"), page_SS_report (f);
+ if (page_mask & ALLOW_AZ ) HDR("Azimuth" ), page_AZ_report (f);
+ // if (page_mask & ALLOW_SPEED) HDR("Dials" ), page_speed_report(f);
+ if (page_mask & ALLOW_STATS) HDR("Statistics" ), page_stats_report(f);
+#ifdef PAGE_LTO
+ if (page_mask & ALLOW_LTO) HDR("LTO"), page_LTO_report(f);
+#endif
+#ifdef PAGE_MAP
+ if (page_mask & ALLOW_MAP) HDR("Plot"), page_map_report(f);
+#endif
+#ifdef PAGE_STRESS
+ if (page_mask & ALLOW_STRESS) HDR("Test"), page_stress_report(f);
+#endif
+#ifdef PAGE_GSM
+ // if (page_mask & ALLOW_GSM) HDR("GSM"), page_GSM_report(f);
+#endif
+#ifdef PAGE_ADD
+ // if (page_mask & ALLOW_ADD) HDR("ADD"), page_ADD_report(f);
+#endif
+#ifdef PAGE_RFI
+ // if (page_mask & ALLOW_RFI ) HDR("RFI" ), page_RFI_report (f);
+ // if (page_mask & ALLOW_AUDIO) HDR("Audio" ), page_audio_report(f);
+ // if (page_mask & ALLOW_BT ) HDR("BlueTooth"), page_BT_report (f);
+#endif
+ notebook_report_trailer(f);
+}
Added: developers/olv/openmoko-agpsui2/src/page_AZ.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_AZ.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_AZ.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,443 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+#include "agps.h"
+#include "sv_bar.h"
+
+void notebook_expose(const char* pageName);
+
+static GtkDrawingArea* AZ;
+static GdkPixmap* AZ_PIX = 0;
+static PangoLayout* AZ_text;
+
+static GdkGC* blue_gc = 0;
+static GdkGC* grey_gc = 0;
+
+extern GdkGC* alloc_color(GdkPixmap* pm, const char* color);
+
+enum
+{
+ MAX_AZ_SEGMENTS = 22
+};
+
+static GdkSegment az_lines[MAX_AZ_SEGMENTS];
+static int nAzLines = 0;
+
+static void
+AZ_add_line(int x0, int y0, int x1, int y1)
+{
+ if (nAzLines >= MAX_AZ_SEGMENTS)
+ {
+ // printf("az_add_line(%d,%d %d,%d) discarded %d\n",
+ // x0, y0, x1, y1, nAzLines);
+ return;
+ }
+ // printf("az_add_line(%d,%d %d,%d) %d\n",
+ // x0, y0, x1, y1, nAzLines);
+ GdkSegment& s = az_lines[nAzLines++];
+ s.x1 = x1;
+ s.y1 = y1;
+ s.x2 = x0;
+ s.y2 = y0;
+}
+
+// #define DEBUG
+
+#ifdef DEBUG
+static void
+debugGC_(int line)
+{
+ printf("%d) blue_gc 0x%x grey_gc 0x%x AZ_PIX 0x%x\n",
+ line, blue_gc, grey_gc, AZ_PIX);
+ fflush(stdout);
+}
+#define debugGC() debugGC_(__LINE__)
+#else
+#define debugGC()
+#endif
+
+bool showTrack = false;
+
+static void
+on_clicked_show_sv_track(GtkWidget* w, gpointer data)
+{
+ const char* text = "Show Track";
+ if (showTrack)
+ {
+ text = "Disable Track";
+ }
+ gtk_button_set_label(GTK_BUTTON(w), text);
+ showTrack = !showTrack;
+}
+
+static void
+AZ_alloc_colors()
+{
+ if (!AZ_PIX) return;
+ if (!blue_gc) blue_gc = alloc_color(AZ_PIX, "Blue");
+ if (!grey_gc) grey_gc = alloc_color(AZ_PIX, "SlateGrey");
+}
+
+static void
+AZ_clear()
+{
+ if (!AZ_PIX) return;
+ GtkWidget* w = GTK_WIDGET(AZ);
+ gdk_draw_rectangle(AZ_PIX, w->style->white_gc, TRUE,
+ 0, 0,
+ w->allocation.width,
+ w->allocation.height);
+}
+
+static gboolean
+configure_AZ_event(GtkWidget* w, GdkEventConfigure* event)
+{
+ debugGC();
+ if (AZ_PIX)
+ {
+ g_object_unref(AZ_PIX);
+ }
+
+ //--------------------------------------------------------------------------
+ // pixmap
+ //--------------------------------------------------------------------------
+ AZ_PIX = gdk_pixmap_new(w->window,
+ w->allocation.width,
+ w->allocation.height, -1);
+ AZ_clear();
+ debugGC();
+ return TRUE;
+}
+
+static gboolean
+expose_AZ_event(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("AZ");
+ if (AZ_PIX)
+ {
+ GdkRectangle& a = event->area;
+ gdk_draw_drawable(w->window,
+ w->style->fg_gc[GTK_WIDGET_STATE(w)],
+ AZ_PIX, a.x, a.y, a.x, a.y, a.width, a.height);
+ }
+ return FALSE;
+}
+
+extern GdkGC* page_SS_getGC(bool used);
+
+static GdkGC*
+getGC(bool used)
+{
+ AZ_alloc_colors();
+ GdkGC* gc = grey_gc;
+ if (used) gc = blue_gc;
+ if (!gc) gc = GTK_WIDGET(AZ)->style->black_gc;
+ return gc;
+}
+
+enum
+{
+ CENTER_XY = 3,
+ CENTER_X = 1,
+ CENTER_Y = 2,
+ CENTER_NONE = 0,
+
+ ALIGN_BOTTOM = 16,
+ ALIGN_RIGHT = 32
+};
+
+static int
+AZ_draw_text(int x, int y, const char* t,
+ int center = CENTER_XY, GdkGC* gc = 0)
+{
+ int w = 0;
+ int h;
+
+ if (!gc) gc = getGC(false);
+ pango_layout_set_text(AZ_text, t, -1);
+ pango_layout_get_pixel_size(AZ_text, &w, &h);
+
+ if (center)
+ {
+ if (center & CENTER_X ) x -= w/2;
+ else if (center & ALIGN_RIGHT ) x -= w;
+ if (center & CENTER_Y ) y -= h/2;
+ else if (center & ALIGN_BOTTOM) y -= h;
+ }
+
+ // printf("AZ_draw_text(%d,%d,\"%s\", %d)\n", x, y, t, center);
+ gdk_draw_layout(AZ_PIX, gc, x, y, AZ_text);
+
+ return w;
+}
+
+static void
+AZ_draw_circle(int r, bool drawText = true)
+{
+ GdkGC* gc = getGC(false);
+
+ int radius = SV_bar::scale_radius(r);
+ int x = LARGE_WINDOW_WIDTH/2 - radius;
+ int y = x;
+ int width = radius * 2;
+ int height = width;
+ int arc0 = 0;
+ int arcN = 360 * DEGREE_64;
+ gdk_draw_arc(AZ_PIX, gc, FALSE,
+ x, y, // starting point
+ width, height,
+ arc0, arcN);
+
+ if (drawText)
+ {
+ char elevation[4];
+ sprintf(elevation, "%d", r);
+ AZ_draw_text(x, LARGE_WINDOW_WIDTH/2, elevation);
+ }
+}
+
+static void
+AZ_draw_radial(int theta, int radius, bool drawText)
+{
+ GdkGC* gc = getGC(false);
+
+ SV_bar r;
+ r.el = radius;
+ r.az = theta;
+
+ int x0;
+ int y0;
+ r.get_xy(x0, y0);
+
+ y0 = LARGE_WINDOW_WIDTH/2 - y0;
+ x0 += LARGE_WINDOW_WIDTH/2;
+
+ int x1;
+ int y1;
+ r.el = 0;
+ r.get_xy(x1, y1);
+
+ y1 = LARGE_WINDOW_WIDTH/2 - y1;
+ x1 += LARGE_WINDOW_WIDTH/2;
+
+ // if (drawText)
+ // printf("radial(%d,%d) x1,y1 = {%d,%d}\n", theta, radius, x1, y1);
+
+ if (drawText)
+ {
+ r.el = -8;
+ r.get_xy(x1, y1);
+ y1 = LARGE_WINDOW_WIDTH/2 - y1;
+ x1 += LARGE_WINDOW_WIDTH/2;
+
+ char str[8];
+ sprintf(str, "%d", theta);
+ AZ_draw_text(x1, y1, str);
+ }
+ else
+ {
+ AZ_add_line(x0, y0, x1, y1);
+ }
+}
+
+static void
+AZ_draw_sv(SV_bar& sv, bool drawDot)
+{
+ int yy;
+ int xx;
+ sv.get_xy(xx, yy);
+
+ yy = LARGE_WINDOW_WIDTH/2 - yy;
+ xx += LARGE_WINDOW_WIDTH/2;
+
+ char prn[4];
+ sprintf(prn, "%d", sv.prn);
+
+ GdkGC* gc = getGC(sv.use);
+
+ // Get the text width.
+ int w;
+ int h;
+ pango_layout_set_text(AZ_text, prn, -1);
+ pango_layout_get_pixel_size(AZ_text, &w, &h);
+
+ //----------------------------------------------
+ // Put a circle down first
+ //
+ // SV used: dark blue circle
+ // SV unused: light grey circle
+ //----------------------------------------------
+ if (h > w) w = h; // w = max(w,h)
+ int radius = 3 + w/2;
+ if (drawDot)
+ {
+ gdk_draw_arc(AZ_PIX, gc, TRUE,
+ xx-radius, yy-radius-1,
+ radius*2, radius*2,
+ 0, 360 * DEGREE_64);
+ }
+ else
+ {
+ //----------------------------------------------
+ // Draw the SV number on the dot
+ //
+ // SV used: white text
+ // SV unused: black text
+ //----------------------------------------------
+ gc = GTK_WIDGET(AZ)->style->black_gc;
+ if (sv.use) gc = GTK_WIDGET(AZ)->style->white_gc;
+ AZ_draw_text(xx, yy, prn, CENTER_XY, gc);
+ }
+
+ // printf("AZ_draw_sv(%d el %d az %d) at %d,%d\n",
+ // sv.prn, sv.el, sv.az, xx, yy);
+}
+
+static void
+AZ_draw_svs()
+{
+ if (!AZ_PIX) return;
+ if (!showTrack)
+ {
+ AZ_clear();
+ }
+
+ int f = LARGE_WINDOW_WIDTH;
+ int h = f/2;
+ int fw = FONT_WIDTH;
+ int fh = FONT_HEIGHT;
+
+ static bool been_here = false;
+ if (!been_here)
+ {
+ been_here = true;
+
+ AZ_add_line(fw,h, f-fw,h); // horizontal line
+ AZ_add_line(h,fh, h,f-fh); // vertical line
+ for (int theta = 15; theta < 360; theta += 15)
+ {
+ int r = 44;
+ switch (theta)
+ {
+ default: break;
+ case 90: case 180: case 270: continue;
+ case 45: case 45 + 90: case 45 + 180: case 45 + 270:
+ r = 74;
+ break;
+ }
+ AZ_draw_radial(theta, r, false);
+ }
+ }
+
+ GdkGC* gc = getGC(false);
+
+ gdk_draw_segments(AZ_PIX, gc, az_lines, nAzLines);
+ AZ_draw_radial(45 , 74, true);
+ AZ_draw_radial(45+ 90, 74, true);
+ AZ_draw_radial(45+180, 74, true);
+ AZ_draw_radial(45+270, 74, true);
+
+ AZ_draw_circle(0, false);
+ AZ_draw_circle(15);
+ AZ_draw_circle(45);
+ AZ_draw_circle(75);
+
+ AZ_draw_text(h, 0, "N", CENTER_X, gc);
+ AZ_draw_text(h, f, "S", CENTER_X | ALIGN_BOTTOM, gc);
+ AZ_draw_text(f, h, "E", CENTER_Y | ALIGN_RIGHT, gc);
+ AZ_draw_text(0, h, "W", CENTER_Y, gc);
+
+ // Draw all the dots.
+ // Then draw all the numbers.
+ for (int b = 0; b < SV_bar::nSS; ++b) AZ_draw_sv(bars[b], true);
+ for (int b = 0; b < SV_bar::nSS; ++b) AZ_draw_sv(bars[b], false);
+
+ gtk_widget_queue_draw_area(GTK_WIDGET(AZ), 0, 0,
+ PIXMAP_WIDTH, PIXMAP_WIDTH);
+}
+
+void
+page_AZ_done()
+{
+ AZ_draw_svs();
+}
+
+GtkWidget*
+page_AZ_create(GtkWidget* window)
+{
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ GtkWidget* table = gtk_table_new(14, 2, TRUE);
+
+ //--------------------------------------------------------------------------
+ // label
+ //--------------------------------------------------------------------------
+ GtkWidget* label = gtk_label_new("Satellite Position");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 0, 1);
+ gtk_widget_show(label);
+
+ AZ_text = gtk_widget_create_pango_layout(label, "");
+
+ //--------------------------------------------------------------------------
+ // window for the satellite position
+ //--------------------------------------------------------------------------
+ GtkWidget* w = gtk_drawing_area_new();
+ AZ = GTK_DRAWING_AREA(w);
+ gtk_drawing_area_size(AZ, PIXMAP_WIDTH, PIXMAP_WIDTH);
+
+ gtk_signal_connect(GTK_OBJECT(w), "configure_event",
+ G_CALLBACK(configure_AZ_event), w);
+
+ gtk_signal_connect(GTK_OBJECT(w), "expose_event",
+ G_CALLBACK(expose_AZ_event), w);
+
+ gtk_widget_set_events(w, GDK_EXPOSURE_MASK);
+ gtk_table_attach_defaults(GTK_TABLE (table), w, 0, 2, 1, 12);
+ gtk_widget_show(w);
+
+ //--------------------------------------------------------------------------
+ // Show SV track
+ //--------------------------------------------------------------------------
+ GtkWidget* button = gtk_button_new_with_label("Show Track");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_show_sv_track), button);
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 1, 2, 13, 14);
+ gtk_widget_show(button);
+
+ gtk_widget_show(table);
+ return table;
+}
+
+void
+page_AZ_report(FILE* f)
+{
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ SV_bar& sv = bars[b];
+ fprintf(f, "PRN %2d Elevation %2d Azimuth %3d %s\n",
+ sv.prn, sv.el, sv.az, (sv.use) ? " " : " unused");
+ }
+}
Added: developers/olv/openmoko-agpsui2/src/page_LTO.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_LTO.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_LTO.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,607 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <signal.h>
+#include <fcntl.h>
+#include "agps.h"
+#include "sv_bar.h"
+#include "lto_download.h"
+#include "liblto.h" // Actual LTO library code from GL.
+
+static GdkGC* blue_gc = 0;
+static GdkGC* grey_gc = 0;
+
+static GtkDrawingArea* LTO;
+static GdkPixmap* LTO_PIX = 0;
+static PangoLayout* LTO_text;
+
+extern "C" void page_lto_file_change();
+
+extern void notebook_expose(const char* pageName);
+
+static void lto_set_download_text(const char* msg);
+static void lto_redraw();
+static void lto_pixmap_update();
+static void lto_draw_percent(bool age, int percent);
+
+GtkLabel* LTO_label;
+GtkLabel* LTO_age_label;
+
+int lto_age_percent = 0;
+static char lto_download_progress_ = ' ';
+static int lto_download_percent_ = 0;
+static bool lto_file_changed = false;
+static void lto_file_lease(bool getLease);
+
+static void
+lto_report(FILE* f)
+{
+ char msg[128];
+ int hours = 0;
+ const char* ltoFile = "/home/root/gpsd/lto2.dat";
+ const char* err = NULL; /*ltoGetExpiration( ltoFile, &hours,
+ msg, sizeof(msg));*/
+ const char* report = err;
+ if (!report) report = msg;
+
+ if (f) fprintf(f, "%s\n", report);
+ else gtk_label_set_text(LTO_age_label, report);
+
+ printf("%s = ltoGetExpiration(%s, %d, %s)\n",
+ (err) ? err : "OK",
+ ltoFile,
+ hours,
+ msg);
+
+ if (err)
+ {
+ lto_age_percent = 0;
+ }
+ else
+ {
+ const int max_hours = 7 * 24; // Assume 7-day LTO.
+ int percent = hours * 100;
+
+ percent += max_hours/2;
+ percent /= max_hours;
+
+ lto_age_percent = percent;
+ printf("Percent %d\n", lto_age_percent);
+ }
+
+ ltoLastLoaded(sizeof(msg), msg);
+
+ if (f) fprintf(f, "%s\nLTO useful for 7 days x %d%%", msg, lto_age_percent);
+ else gtk_label_set_text(LTO_label, msg);
+}
+
+//------------------------------------------------------------------------------
+//
+// Update a label with the sad news
+//
+//------------------------------------------------------------------------------
+
+void
+lto_download_error(const char* msg)
+{
+ gtk_label_set_text(LTO_label, msg);
+}
+
+//------------------------------------------------------------------------------
+//
+// Update the LTO progress message and the.
+// LTO percentage bar.
+//
+//------------------------------------------------------------------------------
+
+static void
+lto_draw_download_progress()
+{
+ char buf[64];
+ sprintf(buf, "Download %d%% complete %c.",
+ lto_download_percent_, lto_download_progress_);
+ lto_set_download_text(buf);
+ lto_draw_percent(false, lto_download_percent_);
+}
+
+void
+lto_download_progress(char progress)
+{
+ lto_download_progress_ = progress;
+ lto_redraw();
+}
+
+void
+lto_download_percent(int n)
+{
+ lto_download_percent_ = n;
+ lto_redraw();
+}
+
+static void
+on_clicked_factory_reset(GtkWidget* w, gpointer d)
+{
+ const char* msg = ltoRemove();
+ if (!msg) msg = "Reset done";
+ lto_download_error(msg);
+ lto_report(0);
+ lto_redraw();
+}
+
+static GdkGC*
+getGC(bool used)
+{
+ GdkGC* gc = grey_gc;
+ if (used)
+ {
+ gc = blue_gc; // used SV is colored blue
+ }
+ if (!gc)
+ {
+ gc = GTK_WIDGET(LTO)->style->black_gc;
+ }
+ return gc;
+}
+
+static void
+lto_set_download_text(const char* msg)
+{
+ int x = 20;
+ int y = 85;
+
+ pango_layout_set_text(LTO_text, msg, -1);
+ gdk_draw_layout(LTO_PIX, getGC(false), x, y, LTO_text);
+
+ // printf("LTO_set_download [%d,%d] %s\n", x, y, msg);
+}
+
+extern void lto_download_stop();
+bool downloading = false;
+GtkButton* lto_download_button = 0;
+
+void
+lto_download_done()
+{
+ downloading = false;
+ gtk_button_set_label(lto_download_button, "Start Download");
+ lto_report(0);
+}
+
+static void
+on_clicked_start_download(GtkWidget* w, gpointer d)
+{
+ // printf("clicked download %d\n", downloading);
+ if (downloading)
+ {
+ lto_download_stop();
+ return;
+ }
+
+ lto_download_percent_ = 0;
+ const char* msg = ltoDownloadStart();
+
+ if (msg)
+ {
+ lto_set_download_text(msg);
+ lto_pixmap_update();
+ }
+ else
+ {
+ lto_set_download_text("LTO download started");
+ lto_report(0);
+ downloading = true;
+
+ gtk_button_set_label(lto_download_button, "Stop Download");
+
+ lto_redraw();
+ }
+}
+
+static void
+lto_pixmap_clear()
+{
+ GtkWidget* w = GTK_WIDGET(LTO);
+ gdk_draw_rectangle(LTO_PIX, w->style->white_gc, TRUE,
+ 0, 0,
+ w->allocation.width,
+ w->allocation.height);
+}
+
+static gboolean
+event_configure_lto(GtkWidget* w, GdkEventConfigure* event)
+{
+ if (LTO_PIX)
+ {
+ g_object_unref(LTO_PIX);
+ }
+
+ //--------------------------------------------------------------------------
+ // pixmap to make the strength bar meter easier to draw
+ //--------------------------------------------------------------------------
+ LTO_PIX = gdk_pixmap_new(w->window,
+ w->allocation.width,
+ w->allocation.height, -1);
+ // printf("LTO pixmap %d x %d\n", w->allocation.width, w->allocation.height);
+ lto_pixmap_clear();
+ return TRUE;
+}
+
+static gboolean
+event_expose_lto(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("LT");
+
+ // TODO: figure out why we're being called so frequently:
+
+ lto_redraw();
+
+ GdkRectangle& a = event->area;
+ gdk_draw_drawable(w->window,
+ w->style->fg_gc[GTK_WIDGET_STATE(w)],
+ LTO_PIX, a.x, a.y, a.x, a.y, a.width, a.height);
+ return FALSE;
+}
+
+static GdkGC*
+alloc_color(GdkPixmap* pm, const char* color)
+{
+ GdkGC* result = 0;
+ if (!pm) return result;
+
+ GdkColormap* map = gdk_colormap_get_system();
+
+ GdkColor blue;
+ if (TRUE == gdk_color_parse(color, &blue))
+ {
+ if (TRUE == gdk_colormap_alloc_color(map, &blue, FALSE, TRUE))
+ {
+ GdkGCValues v;
+ v.foreground = blue;
+ result = gdk_gc_new_with_values(pm, &v, GDK_GC_FOREGROUND);
+ // printf("GC for %s 0x%x\n", color, result);
+ }
+ else printf("Can't alloc %s\n", color);
+ }
+ else printf("Can't parse %s\n", color);
+ return result;
+}
+
+static void
+page_lto_alloc_colors()
+{
+ if (!LTO_PIX) return;
+ if (!blue_gc) blue_gc = alloc_color(LTO_PIX, "Blue");
+ if (!grey_gc) grey_gc = alloc_color(LTO_PIX, "SlateGrey");
+}
+
+static void
+lto_draw_percent(bool age, int percent)
+{
+ page_lto_alloc_colors();
+ GdkGC* gc = GTK_WIDGET(LTO)->style->black_gc;
+
+ int line_width = 1;
+ int adj = 4;
+ int x = 20;
+ int y = 35;
+ int h = 40;
+ int w = 400;
+
+ if (!age)
+ {
+ y += h * 2; // draw the download progress
+ }
+
+ //----------------------------------------------
+ // Draw the rectangle around the percent
+ // (line width is implied in the GC)
+ //----------------------------------------------
+
+ gdk_draw_rectangle(LTO_PIX, gc, FALSE, x, y, w, h);
+
+ if (percent > 100) percent = 100;
+ if (percent <= 0) return;
+
+ //----------------------------------------------
+ // Draw the percentage
+ //----------------------------------------------
+
+ x += adj;
+ y += adj;
+ h -= 2 * adj - line_width;
+ w -= 2 * adj - line_width;
+
+ int progress = 50 + (w * percent);
+ progress /= 100;
+ gc = getGC(true);
+
+ gdk_draw_rectangle(LTO_PIX, gc, TRUE, x, y, progress, h);
+
+ //----------------------------------------------
+ // Draw the percentage text
+ //
+ // % < 60: Draw to the right of the bar.
+ // % > 60: Draw to the left of the bar.
+ //----------------------------------------------
+
+
+ char buf[12];
+ sprintf(buf, "%d%%", percent);
+ pango_layout_set_text(LTO_text, buf, -1);
+
+ int w_text;
+ int h_text;
+ pango_layout_get_pixel_size(LTO_text, &w_text, &h_text);
+
+ y += (h-h_text)/2;
+ if (percent < 60)
+ {
+ x += 4 + progress;
+ // gc = getGC(true); // blue on white looks OK.
+ }
+ else
+ {
+ x -= (4 - progress + w_text);
+ gc = getGC(false); // light grey on blue looks OK.
+ }
+
+ // printf("lto_draw_percent(%s,%d) \"%s\" at (%d %d)\n",
+ // (age) ? "age" : "download", percent, buf, x, y);
+ gdk_draw_layout(LTO_PIX, gc, x, y, LTO_text);
+}
+
+static void
+lto_pixmap_update()
+{
+ gtk_widget_queue_draw_area(GTK_WIDGET(LTO), 0, 0, PIXMAP_WIDTH, PIXMAP_WIDTH);
+}
+
+static void
+lto_redraw()
+{
+ if (!LTO_PIX)
+ {
+ // printf("lto_redraw()/%d: no LTO_PIX\n", __LINE__);
+ return;
+ }
+ lto_pixmap_clear();
+ lto_draw_percent(true, lto_age_percent);
+ if (downloading) lto_draw_download_progress();
+ lto_pixmap_update();
+}
+
+void
+page_LTO_init()
+{
+}
+
+void
+page_LTO_done()
+{
+ lto_redraw();
+}
+
+GtkWidget*
+page_LTO_create(GtkWidget* window)
+{
+ GtkWidget* label;
+ GtkWidget* button;
+ GtkWidget* w;
+ GtkWidget* vbox;
+ GtkWidget* table;
+
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ table = gtk_table_new(14, 2, TRUE);
+
+ //--------------------------------------------------------------------------
+ // Page title label
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("LTO Status");
+ gtk_label_set_justify((GtkLabel*)label, GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 0, 1);
+ gtk_widget_show(label);
+ LTO_age_label = GTK_LABEL(label);
+
+ //--------------------------------------------------------------------------
+ // label
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Expired");
+ gtk_label_set_justify((GtkLabel*)label, GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 1, 2);
+ gtk_widget_show(label);
+ LTO_label = GTK_LABEL(label);
+ LTO_text = gtk_widget_create_pango_layout(label, "");
+
+ //--------------------------------------------------------------------------
+ // window for the LTO bar
+ //--------------------------------------------------------------------------
+ w = gtk_drawing_area_new();
+ LTO = GTK_DRAWING_AREA(w);
+ gtk_drawing_area_size(LTO, 476, 200);
+ gtk_signal_connect(GTK_OBJECT(w), "configure_event",
+ G_CALLBACK(event_configure_lto), w);
+ gtk_signal_connect(GTK_OBJECT(w), "expose_event",
+ G_CALLBACK(event_expose_lto), w);
+ gtk_widget_set_events(w, GDK_EXPOSURE_MASK);
+ gtk_table_attach_defaults(GTK_TABLE (table), w, 0, 2, 3, 8);
+ gtk_widget_show(w);
+
+ //--------------------------------------------------------------------------
+ // Start Download button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("Start Download");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_start_download), button);
+ gtk_table_attach_defaults(GTK_TABLE (table), button, 0, 1, 13, 14);
+ gtk_widget_show(button);
+ lto_download_button = GTK_BUTTON(button);
+
+ //--------------------------------------------------------------------------
+ // Factory Reset button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("Factory Reset");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_factory_reset), button);
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 1, 2, 13, 14);
+ gtk_widget_show(button);
+
+ gtk_widget_show(table);
+
+ lto_report(0);
+ lto_file_lease(true);
+
+ return table;
+}
+
+//-------------------------------------------------------------------------------
+//
+// Experimental feature to update the screen if the LTO file changes.
+// Since the use of SIGIO inside GTK+ is unknown, I have a very
+// risky signal forwarding chaining/cascading/forwarding algorithm.
+// I can't find any references to this technique, so perhaps it won't
+// work.
+//
+// If omgui starts acting strangely, then perhaps use of SIGIO is the
+// problem, and we can't forward it in this manner. Fallbacks are:
+//
+// 0) Drop this entire feature. It is uncertain what to do with the
+// output anyway.
+// 1) Use a different signal. Scan thru all the SIGUSRn until
+// we find one that doesn't have a handler.
+// 2) Fix this forwarding feature.
+//
+//-------------------------------------------------------------------------------
+
+#define OPT_LTO_LEASE
+#ifdef OPT_LTO_LEASE // {
+
+static int lto_file_fd = -1;
+static void lto_file_lease(bool getLease);
+static struct sigaction old_io;
+extern const char* cc_file; // See ltolib.cpp
+
+static bool
+sig_function(void* f)
+{
+ if ((void*)SIG_IGN == f) return false;
+ if ((void*)SIG_DFL == f) return false;
+ return true;
+}
+
+static void
+sig_lto_file_changed(int sigNum, struct siginfo* info, void* v)
+{
+ // Undocumented signal feature:
+ // ucontext_t* u = (ucontext_t*) v;
+
+ if ((info->si_fd == lto_file_fd) && (-1 != lto_file_fd))
+ {
+ printf("LTO file(%d) %s changed\n", lto_file_fd, cc_file);
+
+ // Free the lease right away, and then schedule an update
+ // of the screen info for the near future (somehow)...
+ lto_file_changed = true;
+ lto_file_lease(false);
+ return;
+ }
+
+ // Not our signal, forward it...
+ if (old_io.sa_flags & SA_SIGINFO) // new signal style handler
+ {
+ if (sig_function((void*)old_io.sa_sigaction))
+ {
+ old_io.sa_sigaction(sigNum, info, v);
+ }
+ // else not a function, so don't call
+ }
+ else // old style handler
+ {
+ if (sig_function((void*)old_io.sa_handler))
+ {
+ old_io.sa_handler(sigNum);
+ }
+ }
+}
+
+#define OPT_LTO_LEASE
+#undef OPT_LTO_LEASE
+
+static void
+lto_file_lease(bool getLease)
+{
+#ifdef OPT_LTO_LEASE
+ const char* lto_file = cc_file;
+
+ printf("lto_file_lease(%d) %s have lease\n", getLease,
+ (-1 == lto_file_fd) ? "do not" : "DO");
+
+ if (getLease)
+ {
+ if (-1 != lto_file_fd) return; // already have the lease
+ lto_file_fd = open(lto_file, O_RDONLY);
+
+ lto_file_changed = false;
+
+ fcntl(lto_file_fd, F_SETLEASE, F_RDLCK);
+
+ struct sigaction new_io;
+ new_io.sa_sigaction = sig_lto_file_changed;
+ new_io.sa_flags = SA_SIGINFO;
+ sigemptyset(&new_io.sa_mask);
+ sigaction(SIGIO, &new_io, &old_io);
+ }
+ else // free the lease
+ {
+ if (-1 == lto_file_fd) return; // don't have the lease.
+ fcntl(lto_file_fd, F_SETLEASE, F_UNLCK);
+ close(lto_file_fd);
+ sigaction(SIGIO, &old_io, 0);
+ lto_file_fd = -1;
+ }
+#else
+ printf("lto_file_lease(%d)/%d OPT_LEASE_LTO undefined\n", getLease);
+#endif
+}
+
+#else // } {
+
+static void
+lto_file_lease(bool getLease)
+{
+ printf("NOT SUPPORTED: lto_file_lease(%d) \n", getLease);
+}
+
+#endif // }
+
+
+
+void
+page_LTO_report(FILE* f)
+{
+ lto_report(f);
+}
Added: developers/olv/openmoko-agpsui2/src/page_SS.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_SS.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_SS.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,917 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "agps.h"
+#include "sv_bar.h"
+
+SV_bar bars[MAX_SVS];
+int SV_bar::nSS = 0;
+bool SV_bar::changed = false;
+int SV_bar::leastSamplesAveraged = 0;
+
+static GdkGC* blue_gc = 0;
+static GdkGC* grey_gc = 0;
+
+static GtkDrawingArea* SS;
+static GdkPixmap* SS_PIX = 0;
+int dbm = 0;
+static PangoLayout* SS_text;
+GtkWidget* top4_button;
+
+// KLUDGE for A3 or larger fonts only:
+// bool large_font = true;
+// bool a3_hardware = true;
+#define large_font 1
+#define a3_hardware 1
+
+inline int
+format_ss(int dbHz)
+{
+ if (dbm) dbHz += DB_HZ_to_DBM;
+
+ if (large_font || a3_hardware)
+ {
+ if (dbHz < 0) dbHz = -dbHz;
+ }
+ return dbHz;
+}
+
+inline double
+format_ssf(double dbHz)
+{
+ if (dbm) return dbHz + DB_HZ_to_DBM;
+ return dbHz;
+}
+
+extern void notebook_expose(const char* pageName);
+
+static void SS_draw_bars();
+void page_SS_use_prn(int prn);
+void page_SS_have_prn(int prn, int ss, int el, int az);
+static double get_top_four_SVS();
+unsigned long msTime(void);
+
+// Return a number between -100 and +100 along the X and Y axes.
+
+const double PI = 3.1415926535;
+
+int SV_bar::scale_radius(int r)
+{
+ r = 90 - r;
+ r *= LARGE_WINDOW_WIDTH/2;
+ r += 45;
+ return r/90;
+}
+
+void SV_bar::get_xy(int&x, int& y)
+{
+ float radius = (float) scale_radius(el);
+ float theta = (float) -(az - 90);
+ float rad = theta * PI/180.0;
+
+ float fx = radius * cos(rad);
+ float fy = radius * sin(rad);
+ x = (int) (fx + 0.5);
+ y = (int) (fy + 0.5);
+
+ //printf("get_xy: r %f, theta %f rad %f fx %f fy %f\n",
+ // radius,theta, rad, fx, fy);
+}
+
+GtkLabel* ss_label;
+
+void SS_reset_max_min()
+{
+ unsigned long ms = msTime();
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ SV_bar& sv = bars[b];
+ if (!sv.use) continue;
+
+ sv.ss_max_time = ms;
+ sv.ss_min_time = ms;
+ sv.ss_max = sv.ss;
+ sv.ss_min = sv.ss;
+ }
+}
+
+void SS_reset_average()
+{
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ SV_bar& sv = bars[b];
+ sv.nAvg = 0;
+ sv.sumAvg = 0;
+ sv.indexAvg = 0;
+ }
+}
+
+static void
+on_clicked_reset_max_min(GtkWidget* w, gpointer d)
+{
+ SS_reset_max_min();
+ SS_draw_bars();
+}
+
+static void
+reset_top4()
+{
+ gtk_button_set_label(GTK_BUTTON(top4_button), "Top 4 SV");
+}
+
+static void
+on_clicked_top4(GtkWidget* w, gpointer data)
+{
+ double top4 = format_ssf(get_top_four_SVS());
+ int nSamples = SV_bar::leastSamplesAveraged;
+ if (nSamples)
+ {
+ char buf[64];
+ sprintf(buf,"Top 4 %.1f (%d)", top4, nSamples);
+ gtk_button_set_label(GTK_BUTTON(w), buf);
+ }
+ else
+ {
+ reset_top4();
+ }
+}
+
+static void
+on_clicked_reset_average(GtkWidget* w, gpointer d)
+{
+ SS_reset_average();
+ reset_top4();
+ SS_draw_bars();
+}
+
+static void
+on_ss_units_change()
+{
+ const char* units = "Signal Strength (dB.Hz)";
+ if (dbm) units = "Signal Strength (dBm)";
+ gtk_label_set_text(ss_label, units);
+}
+
+static void
+on_clicked_dbm(GtkWidget* widget, gpointer data)
+{
+ dbm = 1 - dbm;
+ gtk_button_set_label(GTK_BUTTON(data), (dbm) ? "dBm" : "C/N0");
+ on_ss_units_change();
+ reset_top4();
+ SS_draw_bars();
+}
+
+static void
+SS_clear()
+{
+ GtkWidget* w = GTK_WIDGET(SS);
+ gdk_draw_rectangle(SS_PIX, w->style->white_gc, TRUE,
+ 0, 0,
+ w->allocation.width,
+ w->allocation.height);
+}
+
+static gboolean
+configure_SS_event(GtkWidget* w, GdkEventConfigure* event)
+{
+ if (SS_PIX)
+ {
+ g_object_unref(SS_PIX);
+ }
+
+ //--------------------------------------------------------------------------
+ // pixmap to make the strength bar meter easier to draw
+ //--------------------------------------------------------------------------
+ SS_PIX = gdk_pixmap_new(w->window,
+ w->allocation.width,
+ w->allocation.height, -1);
+ SS_clear();
+ return TRUE;
+}
+
+static gboolean
+expose_SS_event(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("SS");
+ GdkRectangle& a = event->area;
+ gdk_draw_drawable(w->window,
+ w->style->fg_gc[GTK_WIDGET_STATE(w)],
+ SS_PIX, a.x, a.y, a.x, a.y, a.width, a.height);
+ return FALSE;
+}
+
+void
+page_SS_done()
+{
+ if (!SV_bar::changed) return;
+ SV_bar::changed = false;
+ SS_draw_bars();
+}
+
+static int
+SS_width(int maxWidth)
+{
+ int n = SV_bar::nSS;
+ if (SV_bar::nSS < 1)
+ {
+ n = 1;
+ }
+ int seps = n+1;
+ return (maxWidth - seps * SEP_WIDTH) / n;
+}
+
+static GdkGC*
+getGC(bool used)
+{
+ GdkGC* gc = grey_gc;
+ if (used)
+ {
+ gc = blue_gc; // used SV is colored blue
+ }
+ if (!gc)
+ {
+ gc = GTK_WIDGET(SS)->style->black_gc;
+ }
+ return gc;
+}
+
+static void
+SS_draw_line(int x0, int y0, int x1, int y1)
+{
+ printf("AZ_draw_line(%d,%d,%d,%d)\n", x0, y0, x1, y1);
+ gdk_draw_line(SS_PIX, getGC(false), x0, y0, x1, y1);
+}
+
+//------------------------------------------------------------------------------------
+//
+// dbHz_to_pixels()
+//
+// dBm C/N0 Pixels Use
+// -120 53 BAR_HEIGHT Maximum
+// -133 40 <scaled properly> Typical
+// -163 10 0 Minimum
+//
+//------------------------------------------------------------------------------------
+
+int dbHz_to_pixels(int dbHz)
+{
+ if (dbHz >= 53) return BAR_HEIGHT;
+ if (dbHz <= 10) return 0;
+ dbHz -= 10;
+ dbHz *= BAR_HEIGHT;
+ dbHz += 21; // Rounding.
+ dbHz /= 43;
+ return dbHz;
+}
+
+GdkGC*
+alloc_color(GdkPixmap* pm, const char* color)
+{
+ GdkGC* result = 0;
+ if (!pm) return result;
+
+ GdkColormap* map = gdk_colormap_get_system();
+
+ GdkColor blue;
+ if (TRUE == gdk_color_parse(color, &blue))
+ {
+ if (TRUE == gdk_colormap_alloc_color(map, &blue, FALSE, TRUE))
+ {
+ GdkGCValues v;
+ v.foreground = blue;
+ result = gdk_gc_new_with_values(pm, &v, GDK_GC_FOREGROUND);
+ // printf("GC for %s 0x%x\n", color, result);
+ }
+ else printf("Can't alloc %s\n", color);
+ }
+ else printf("Can't parse %s\n", color);
+ return result;
+}
+
+void
+page_SS_alloc_colors()
+{
+ if (!SS_PIX) return;
+ if (!blue_gc) blue_gc = alloc_color(SS_PIX, "Blue");
+ if (!grey_gc) grey_gc = alloc_color(SS_PIX, "SlateGrey");
+}
+
+//-------------------------------------------------------------------------------------
+//
+// SS_draw_el()
+//
+// Draw a black filled arc showing the elevation at the bottom of the bar.
+// (x,y) should be the lower-left corner of the signal strength bar.
+//
+// Max width is 40.
+//
+//-------------------------------------------------------------------------------------
+
+static void
+SS_draw_el(SV_bar& sv, int x, int y, int width)
+{
+ if (!sv.use) return;
+
+ int arcN = sv.el * DEGREE_64;
+ if (sv.el < MIN_ELEVATION) arcN = MIN_ELEVATION * DEGREE_64;
+
+ const int max_width = 50;
+ if (width > max_width)
+ {
+ x += (width - max_width)/2;
+ width = max_width;
+ }
+
+ gdk_draw_arc(SS_PIX, GTK_WIDGET(SS)->style->black_gc, TRUE,
+ x-width, y-width,
+ width*2, width*2,
+ 0, arcN);
+}
+
+enum
+{
+ SS_SMALL = 1,
+ SS_TEXT = 2
+};
+
+static void
+SS_draw_ss(int ss, int y, int w, int flags)
+{
+ page_SS_alloc_colors();
+ GdkGC* gc = getGC(false);
+
+ int font_height = 16; // TODO: see how to get this.
+ int barHeightPixels = dbHz_to_pixels(ss);
+
+ int base_y = y + BAR_HEIGHT + 2 * font_height;
+
+ int h = 3;
+ int r_y = base_y - barHeightPixels - 1;
+
+ //----------------------------------------------
+ // Draw the signal strength rule
+ //----------------------------------------------
+ if (flags & SS_SMALL)
+ {
+ ++r_y;
+ h = 1;
+ }
+ gdk_draw_rectangle(SS_PIX, gc, TRUE, 0, r_y, w, h);
+
+ //----------------------------------------------
+ // Draw the signal strength text
+ //----------------------------------------------
+ if (flags & SS_TEXT)
+ {
+ char dbmString[8];
+ sprintf(dbmString, "%d", format_ss(ss));
+ pango_layout_set_text(SS_text, dbmString, -1);
+ if (flags & SS_SMALL) w += SEP_WIDTH;
+ gdk_draw_layout(SS_PIX, getGC(false),
+ w + SEP_WIDTH, r_y - FONT_HEIGHT/2, SS_text);
+ }
+}
+
+static void
+SS_draw_bar(SV_bar& sv, int x, int y, int width, bool barOnly)
+{
+ int font_height = 16; // TODO: see how to get this.
+
+ int barHeightPixels = dbHz_to_pixels(sv.ss);
+
+ page_SS_alloc_colors();
+
+ //----------------------------------------------
+ // Draw the signal strength bar
+ //----------------------------------------------
+
+ int base_y = y + BAR_HEIGHT + 2*font_height;
+ int r_y = base_y - barHeightPixels;
+ int r_height = barHeightPixels;
+
+ GdkGC* gc = getGC(sv.use);
+
+ if (barOnly)
+ gdk_draw_rectangle(SS_PIX, gc, TRUE, x, r_y, width, r_height);
+
+ //----------------------------------------------
+ // Draw the elevation arc
+ //----------------------------------------------
+
+ SS_draw_el(sv, x, base_y, width);
+
+ //----------------------------------------------
+ // Draw the minimum level (if it exists)
+ // Draw the maximim level (if it exists)
+ //----------------------------------------------
+ if (sv.use && barOnly)
+ {
+ GdkGC* black_gc = GTK_WIDGET(SS)->style->black_gc;
+ if (sv.ss_min_time)
+ {
+ barHeightPixels = dbHz_to_pixels(sv.ss_min);
+ r_y = base_y - barHeightPixels;
+ gdk_draw_rectangle(SS_PIX, black_gc, TRUE,
+ x + width/4, r_y - 1, width/2, 3);
+ }
+ if (sv.ss_max_time)
+ {
+ barHeightPixels = dbHz_to_pixels(sv.ss_max);
+ r_y = base_y - barHeightPixels;
+ gdk_draw_rectangle(SS_PIX, black_gc, TRUE,
+ x, r_y - 1, width, 3);
+ }
+ }
+
+ //----------------------------------------------
+ // Draw the average SS text
+ //----------------------------------------------
+
+ if (!barOnly)
+ {
+ int yy = y;
+ int xx = x + 3;
+
+ //----------------------------------------------
+ // Draw the signal strength average
+ // Draw the signal strength text
+ //----------------------------------------------
+
+ if (sv.use)
+ {
+ char dbmString[8];
+
+ int i_dbm = sv.avg_ss();
+ if (!i_dbm)
+ {
+ sprintf(dbmString, "-");
+ xx += 4;
+ }
+ else
+ {
+ sprintf(dbmString, "%d", format_ss(sv.avg_ss()));
+ }
+
+ pango_layout_set_text(SS_text, dbmString, -1);
+ gdk_draw_layout(SS_PIX, gc, xx, yy, SS_text);
+
+ sprintf(dbmString, "%d", format_ss(sv.ss));
+ pango_layout_set_text(SS_text, dbmString, -1);
+ gdk_draw_layout(SS_PIX, gc, x+3, y + font_height + 4, SS_text);
+ }
+
+ //----------------------------------------------
+ // Draw the PRN text
+ //----------------------------------------------
+
+ char prn[4];
+ sprintf(prn, "%d", sv.prn);
+ pango_layout_set_text(SS_text, prn, -1);
+ xx = (sv.prn > 9) ?
+ x + width/2 - 12 // TODO: center this.
+ : x + width/2 - 5; // TODO: center this.
+ yy = y + BAR_HEIGHT + 2*font_height;
+ gdk_draw_layout(SS_PIX, gc, xx, yy, SS_text);
+ // printf("PRN \"%s\" at {x %d y %d}\n", prn, xx, yy);
+ }
+}
+
+static void
+SS_draw_bars()
+{
+ if (!SS_PIX) return;
+ SS_clear();
+
+ // Leave some space to the right for the markers, etc.
+ int w = SS_width(PIXMAP_WIDTH - 60);
+ int indicator_w = SV_bar::nSS * (SEP_WIDTH + w) + SEP_WIDTH;
+ int y = 10;
+
+ //----------------------------------------------
+ // Draw the small SS horizontal lines
+ //----------------------------------------------
+ if (dbm)
+ {
+ SS_draw_ss(48, y, indicator_w, SS_SMALL); // -125 dBm MAX
+ SS_draw_ss(43, y, indicator_w, SS_TEXT); // -130 dBm
+ SS_draw_ss(38, y, indicator_w, SS_SMALL);
+ SS_draw_ss(33, y, indicator_w, SS_TEXT); // -140 dBm
+ SS_draw_ss(28, y, indicator_w, SS_SMALL);
+ SS_draw_ss(23, y, indicator_w, SS_TEXT); // -150 dBm
+ SS_draw_ss(18, y, indicator_w, SS_SMALL);
+ SS_draw_ss(13, y, indicator_w, SS_TEXT); // -160 dBm MIN
+ }
+ else
+ {
+ SS_draw_ss(50, y, indicator_w, SS_TEXT); // 50 dBm MAX
+ SS_draw_ss(45, y, indicator_w, SS_SMALL);
+ SS_draw_ss(40, y, indicator_w, SS_TEXT);
+ SS_draw_ss(35, y, indicator_w, SS_SMALL);
+ SS_draw_ss(30, y, indicator_w, SS_TEXT);
+ SS_draw_ss(25, y, indicator_w, SS_SMALL);
+ SS_draw_ss(20, y, indicator_w, SS_TEXT);
+ SS_draw_ss(15, y, indicator_w, SS_SMALL);
+ SS_draw_ss(13, y, indicator_w, SS_SMALL | SS_TEXT); // -160 dBm MIN
+ }
+
+ int x = SEP_WIDTH;
+ if (SV_bar::nSS)
+ {
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ SS_draw_bar(bars[b], x, y, w, true );
+ x += SEP_WIDTH + w;
+ }
+ }
+
+ x = SEP_WIDTH;
+ if (SV_bar::nSS)
+ {
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ SS_draw_bar(bars[b], x, y, w, false);
+ x += SEP_WIDTH + w;
+ }
+ }
+
+ //----------------------------------------------
+ // Draw the "avg" SS text
+ //----------------------------------------------
+ pango_layout_set_text(SS_text, "avg", -1);
+ gdk_draw_layout(SS_PIX, GTK_WIDGET(SS)->style->black_gc, indicator_w, y, SS_text);
+
+ // gtk_widget_queue_draw_area(GTK_WIDGET(SS), 0, 0, 400, 500);
+ gtk_widget_queue_draw_area(GTK_WIDGET(SS), 0, 0, PIXMAP_WIDTH, PIXMAP_WIDTH);
+}
+
+//------------------------------------------------------------------------------
+//
+// get_top_SV
+//
+// Return the signal strength of the strongest SV
+// that is not in MASK
+//
+//------------------------------------------------------------------------------
+
+#define BIT(b) (1 << (b))
+
+static int get_top_SV(int& mask)
+{
+ int our_mask = 0;
+ int max = 0;
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ int m = BIT(b);
+ if (m & mask) continue;
+ SV_bar& sv = bars[b];
+ int avg = sv.avg_ss();
+ if (avg > max)
+ {
+ our_mask = m;
+ max = avg;
+ int n = sv.nAvg;
+ if (n > N_AVG) n = N_AVG;
+ if (n < SV_bar::leastSamplesAveraged)
+ {
+ SV_bar::leastSamplesAveraged = n;
+ }
+ }
+ }
+ mask |= our_mask;
+ printf("top 4: 0x%x %d\n", our_mask, max);
+ return max;
+}
+
+static double get_top_four_SVS()
+{
+ int mask = 0;
+ double sum = 0;
+ int total = 0;
+ int avg;
+ SV_bar::leastSamplesAveraged = N_AVG;
+
+ avg = get_top_SV(mask);
+ sum += avg;
+
+ if (!avg)
+ {
+ SV_bar::leastSamplesAveraged = 0;
+ return 0.0;
+ }
+ avg = get_top_SV(mask); sum += avg; if (!avg) return sum;
+ avg = get_top_SV(mask); sum += avg; if (!avg) return sum/2.0;
+ avg = get_top_SV(mask); sum += avg; if (!avg) return sum/3.0;
+
+ return sum / 4.0;
+}
+
+static int
+update_prn(int prn, int ss, int el, int az)
+{
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ if (prn == bars[b].prn)
+ {
+ SV_bar& sv = bars[b];
+ if ((sv.el == el) && (sv.az == az) && (sv.ss == ss))
+ {
+ return 0;
+ }
+ if ((sv.el != el) || (sv.az != az))
+ {
+ // printf("Change PRN %d el %d-->%d az %d-->%d\n",
+ // sv.prn, sv.el, el, sv.az, az);
+ sv.el = el;
+ sv.az = az;
+ }
+ sv.ss = ss;
+ sv.lastUpdate = msTime();
+ if ((ss > sv.ss_max)) // || ((sv.lastUpdate - sv.ss_max_time) > 1000*60))
+ {
+ sv.ss_max_time = sv.lastUpdate;
+ sv.ss_max = ss;
+ }
+
+ // Either we have a new minimum signal strength; OR
+ // We time-out the min signal
+ if ((ss < sv.ss_min)) // || ((sv.lastUpdate - sv.ss_min_time) > 1000*60))
+ {
+ sv.ss_min_time = sv.lastUpdate;
+ sv.ss_min = ss;
+ }
+ return 1;
+ }
+ }
+ return -1;
+}
+
+static int
+findUnusedSV()
+{
+ unsigned long oldest_ms = msTime();
+ int oldest = -1;
+
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ if (bars[b].use) continue;
+ if (bars[b].lastUpdate < oldest_ms)
+ {
+ oldest_ms = bars[b].lastUpdate;
+ oldest = b;
+ }
+ }
+ return oldest;
+}
+
+unsigned long msTime(void);
+
+static void
+use_prn(int prn)
+{
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ SV_bar& sv = bars[b];
+ if (prn == sv.prn)
+ {
+ if (!sv.use)
+ {
+ SV_bar::changed = true;
+ sv.use = true;
+ }
+ sv.add_ss();
+ sv.lastUpdate = msTime();
+ return;
+ }
+ }
+}
+
+void
+page_SS_unuse_prns()
+{
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ bars[b].use = false;
+ }
+}
+
+void
+page_SS_use_prn(int prn)
+{
+ // printf("page_SS_use_prn(%d)\n", prn);
+ if (prn < 1) return;
+ if (prn > 32) return; // Haven't launched PRN 33 yet.
+ use_prn(prn);
+}
+
+void
+page_SS_have_prn(int prn, int ss, int el, int az)
+{
+ // printf("page_SS_have_prn(%d %d %d:%d) %d\n", prn, ss, el, az, SV_bar::nSS);
+ if (prn < 1) return;
+ if (prn > 32) return; // Haven't launched PRN 33 yet.
+
+ switch (update_prn(prn, ss, el, az))
+ {
+ case 0:
+ return;
+ case 1:
+ SV_bar::changed = true;
+ return;
+ default:
+ break;
+ }
+
+ int nextSV = SV_bar::nSS;
+ if (SV_bar::nSS < MAX_SVS)
+ {
+ // TODO: remove unused SVs.
+ ++SV_bar::nSS;
+ }
+ else
+ {
+ nextSV = findUnusedSV();
+ if (nextSV < 0) return;
+ }
+
+ // printf("add %d = {%d %d}\n", nextSV, prn, ss);
+ SV_bar& sv = bars[nextSV];
+ sv.init();
+ sv.prn = prn;
+ sv.ss = ss;
+ sv.el = el;
+ sv.az = az;
+ sv.lastUpdate = msTime();
+
+ SV_bar::changed = true;
+}
+
+void
+page_SS_init()
+{
+ memset(bars, 0, sizeof(bars));
+ SV_bar::nSS = 0;
+}
+
+GtkWidget*
+page_SS_create(GtkWidget* window)
+{
+ GtkWidget* label;
+ GtkWidget* button;
+ GtkWidget* w;
+ GtkWidget* vbox;
+ GtkWidget* table;
+
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ table = gtk_table_new(14, 2, TRUE);
+
+ //--------------------------------------------------------------------------
+ // label
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Signal Strength (db.Hz)");
+ gtk_label_set_justify((GtkLabel*)label, GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 0, 1);
+ gtk_widget_show(label);
+ ss_label = GTK_LABEL(label);
+
+ SS_text = gtk_widget_create_pango_layout(label, "");
+
+ //--------------------------------------------------------------------------
+ // window for the strength bar meters
+ //--------------------------------------------------------------------------
+ w = gtk_drawing_area_new();
+ SS = GTK_DRAWING_AREA(w);
+ gtk_drawing_area_size(SS, 500, 500);
+
+ gtk_signal_connect(GTK_OBJECT(w), "configure_event",
+ G_CALLBACK(configure_SS_event), w);
+
+ gtk_signal_connect(GTK_OBJECT(w), "expose_event",
+ G_CALLBACK(expose_SS_event), w);
+
+ gtk_widget_set_events(w, GDK_EXPOSURE_MASK);
+ gtk_table_attach_defaults(GTK_TABLE (table), w, 0, 2, 1, 12);
+ gtk_widget_show(w);
+
+#if 0
+ //--------------------------------------------------------------------------
+ // Reset Average button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("Reset Max");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_reset_max_min), button);
+ gtk_table_attach_defaults(GTK_TABLE (table), button, 0, 1, 12, 13);
+ gtk_widget_show(button);
+#else
+ //--------------------------------------------------------------------------
+ // Reset max/min button
+ //--------------------------------------------------------------------------
+ GtkWidget* box = gtk_hbox_new (FALSE, 2);
+
+ button = gtk_button_new_with_label("Reset max");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_reset_max_min), button);
+ gtk_widget_show(button);
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+
+ //--------------------------------------------------------------------------
+ // Reset average button
+ //--------------------------------------------------------------------------
+
+ button = gtk_button_new_with_label("Reset avg");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_reset_average), button);
+ gtk_widget_show(button);
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+
+ gtk_widget_show(box);
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 1, 12, 13);
+#endif
+
+ //--------------------------------------------------------------------------
+ // dBm or C/N0 button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("dBm");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_dbm), button);
+ gtk_table_attach_defaults(GTK_TABLE (table), button, 0, 1, 13, 14);
+ gtk_widget_show(button);
+
+ //--------------------------------------------------------------------------
+ // Top 4 SV Average button
+ //--------------------------------------------------------------------------
+ top4_button = gtk_button_new_with_label("");
+ g_signal_connect(G_OBJECT(top4_button), "clicked",
+ G_CALLBACK(on_clicked_top4), top4_button);
+ gtk_table_attach_defaults(GTK_TABLE(table), top4_button, 1, 2, 13, 14);
+ reset_top4();
+ gtk_widget_show(top4_button);
+
+ gtk_widget_show(table);
+ return table;
+}
+
+static void
+SS_report_bar(SV_bar& sv, FILE* f)
+{
+ fprintf(f, " %2d", sv.prn);
+ fprintf(f, " %2d", sv.ss);
+
+ int i_dbm = sv.avg_ss();
+ if (i_dbm) fprintf(f, " %2d", i_dbm);
+ else fprintf(f, " ");
+
+ if (sv.ss_min_time) fprintf(f, " %2d", sv.ss_min);
+ else fprintf(f, " ");
+
+ if (sv.ss_max_time) fprintf(f, " %2d", sv.ss_max);
+ else fprintf(f, " ");
+
+ fprintf(f, " %2d", sv.el);
+ fprintf(f, " %3d", sv.az);
+
+ if (sv.use) fprintf(f, " y\n");
+ else fprintf(f, " UNUSED\n");
+}
+
+void
+page_SS_report(FILE* f)
+{
+ fprintf(f, "PRN dB.Hz AVG min MAX Elevation Azimuth Used\n");
+ for (int b = 0; b < SV_bar::nSS; ++b)
+ {
+ SS_report_bar(bars[b], f);
+ }
+ fprintf(f, "\n");
+
+ double top4 = format_ssf(get_top_four_SVS());
+ int nSamples = SV_bar::leastSamplesAveraged;
+ if (nSamples)
+ {
+ fprintf(f, "Top 4 SVs %.1f (%d)\n", top4, nSamples);
+ }
+}
Added: developers/olv/openmoko-agpsui2/src/page_add.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_add.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_add.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <stdlib.h>
+
+// Dummy page to show how to add another page easily.
+
+GtkWidget* add_msg;
+
+static void
+page_ADD_init()
+{
+}
+
+static void
+on_clicked_connect(GtkWidget *widget, gpointer data)
+{
+ g_print("User has clicked button connect\n");
+}
+
+static void
+on_clicked_dial(GtkWidget *widget, gpointer data)
+{
+ g_print("User has clicked button dial\n");
+}
+
+static void
+on_clicked_acp(GtkWidget *widget, gpointer data)
+{
+ g_print("User has clicked button accept\n");
+}
+
+static void
+on_clicked_hangup(GtkWidget *widget, gpointer data)
+{
+ g_print("User has clicked button hangup\n");
+}
+
+GtkWidget*
+page_ADD_create(GtkWidget* window)
+{
+ GtkWidget* table = gtk_table_new(14,10,TRUE);
+ GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_table_attach_defaults (GTK_TABLE (table), scrolled_window, 0, 10, 0, 11);
+
+ GtkWidget* hb1 = gtk_frame_new ("Test Message");
+ add_msg = gtk_label_new("");
+ gtk_label_set_justify((GtkLabel*)add_msg, GTK_JUSTIFY_LEFT);
+ gtk_container_add (GTK_CONTAINER (hb1), add_msg);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
+ hb1);
+
+ GtkWidget* frame_table = gtk_table_new (2, 2, TRUE);
+ GtkWidget* start_btn = gtk_button_new_with_label ("Connect");
+ g_signal_connect(G_OBJECT(start_btn),
+ "clicked",G_CALLBACK (on_clicked_connect), NULL);
+ gtk_table_attach_defaults (GTK_TABLE (frame_table), start_btn, 0, 1, 0, 1);
+
+ GtkWidget* dial_btn = gtk_button_new_with_label ("Dial 112");
+ g_signal_connect(G_OBJECT(dial_btn),
+ "clicked",G_CALLBACK (on_clicked_dial), NULL);
+ gtk_table_attach_defaults (GTK_TABLE (frame_table), dial_btn, 1, 2, 0, 1);
+
+ GtkWidget* acp_btn = gtk_button_new_with_label ("Accept");
+ g_signal_connect(G_OBJECT(acp_btn), "clicked", G_CALLBACK(on_clicked_acp), NULL);
+ gtk_table_attach_defaults (GTK_TABLE (frame_table), acp_btn, 0, 1, 1, 2);
+ GtkWidget* hang_btn = gtk_button_new_with_label ("Hang up");
+ g_signal_connect(G_OBJECT(hang_btn),
+ "clicked", G_CALLBACK(on_clicked_hangup), NULL);
+ gtk_table_attach_defaults (GTK_TABLE (frame_table), hang_btn, 1, 2, 1, 2);
+ gtk_table_attach_defaults(GTK_TABLE (table), frame_table, 0, 10, 11, 14);
+
+ gtk_widget_show(scrolled_window);
+ gtk_widget_show(hb1);
+ gtk_widget_show(add_msg);
+ gtk_widget_show(frame_table);
+ gtk_widget_show(start_btn);
+ gtk_widget_show(dial_btn);
+ gtk_widget_show(acp_btn);
+ gtk_widget_show(hang_btn);
+ gtk_widget_show(table);
+
+ printf("%s/%d\n", __FILE__, __LINE__);
+ return table;
+}
+
+void
+page_ADD_report(FILE* f)
+{
+ fprintf(f, "Say something about %s/%d\n", __FILE__, __LINE__);
+}
Added: developers/olv/openmoko-agpsui2/src/page_log.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_log.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_log.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,135 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#define MAX_LINES 40
+
+enum {
+ COLUMN_TIME,
+ COLUMN_NMEA,
+ N_COLUMNS
+};
+
+static GtkListStore *store;
+static int num_lines;
+static gboolean locked;
+
+unsigned long int runtime_ms();
+
+void page_log_append(const char *nmea)
+{
+ GtkTreeIter iter;
+
+ if (!store || locked)
+ return;
+
+ if (num_lines >= MAX_LINES)
+ {
+ if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
+ {
+ if (gtk_list_store_remove(store, &iter))
+ num_lines--;
+ }
+ }
+
+ if (num_lines < MAX_LINES)
+ {
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, COLUMN_TIME, runtime_ms(), COLUMN_NMEA, nmea, -1);
+ num_lines++;
+ }
+}
+
+static GtkTreeModel *create_model(void)
+{
+ store = gtk_list_store_new(N_COLUMNS, G_TYPE_INT, G_TYPE_STRING);
+
+ return GTK_TREE_MODEL(store);
+}
+
+#ifdef SELF_PRODUCING
+static gboolean add_nmea(gpointer data)
+{
+ gchar buf[256];
+
+ g_snprintf(buf, sizeof(buf), "%d", num_lines);
+
+ page_log_append(buf);
+
+ return TRUE;
+}
+#endif
+
+static void on_lock_clicked(GtkWidget *w, gpointer data)
+{
+ locked = !locked;
+
+ gtk_button_set_label(GTK_BUTTON(w), (locked) ? "Unlock" : "Lock");
+}
+
+GtkWidget*
+page_log_create(GtkWidget* window)
+{
+ GtkWidget *vbox, *button, *scroll, *view;
+ GtkTreeModel *model;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *selection;
+ GtkCellRenderer *cell;
+
+ model = create_model();
+ view = gtk_tree_view_new_with_model(model);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+
+ cell = gtk_cell_renderer_text_new();
+
+ column = gtk_tree_view_column_new_with_attributes("Time", cell, "text", COLUMN_TIME, NULL);
+ gtk_tree_view_column_set_min_width(GTK_TREE_VIEW_COLUMN(column), 80);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
+
+ column = gtk_tree_view_column_new_with_attributes("NMEA", cell, "text", COLUMN_NMEA, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
+
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add(GTK_CONTAINER(scroll), view);
+
+ button = gtk_button_new_with_label("Lock");
+ g_signal_connect(button, "clicked", G_CALLBACK(on_lock_clicked), NULL);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start_defaults(GTK_BOX(vbox), scroll);
+ gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
+ gtk_widget_show_all(vbox);
+
+#ifdef SELF_PRODUCING
+ g_timeout_add(500, add_nmea, NULL);
+#endif
+
+ return vbox;
+}
Added: developers/olv/openmoko-agpsui2/src/page_main.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_main.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_main.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,440 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <stdlib.h>
+#include "agps.h"
+
+extern void notebook_expose(const char* pageName);
+
+#ifndef AGPS_H_
+#include "agps.h"
+#endif
+
+extern void page_stress_on(void);
+extern void page_stress_msg(const char* msg);
+
+extern void create_range_controls(GtkWidget* window, GtkWidget* vbox, bool test);
+extern const char* gllin_detect(void);
+extern const char* gllin_start(void);
+extern const char* gllin_stop(void);
+extern void gllin_reset(char c);
+extern void agps_cb_start(GtkWidget* label);
+extern void agps_cb_stop(void);
+extern void agps_stop(void);
+extern void clearStats(void);
+extern void page_pm_batch_start();
+
+extern GtkLabel* agpsLabel;
+extern void NMEA_MSG(const char* msg);
+
+static bool gllinRunning = false;
+bool doing_ptf = false;
+extern bool doing_batch;
+extern bool doing_stress;
+
+//-------------------------------------------------------------------------------------
+//
+// OMGUI versions
+//
+//-------------------------------------------------------------------------------------
+
+#define OMGUI_MAJOR 0
+#define OMGUI_MINOR 20
+
+const char*
+page_main_omgui_version(void)
+{
+ static char buf[64];
+ sprintf(buf, "OpenMoko GPS UI v%d.%02d", OMGUI_MAJOR, OMGUI_MINOR);
+ return buf;
+}
+
+//-------------------------------------------------------------------------------------
+//
+// millisecond timer()
+//
+//-------------------------------------------------------------------------------------
+
+unsigned long msTime(void)
+{
+ struct timespec t;
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ unsigned long ms = t.tv_nsec/1000000;
+ ms += t.tv_sec * 1000;
+ return ms;
+}
+
+static unsigned long msStart;
+
+void runtime_init()
+{
+ msStart = msTime();
+}
+
+unsigned long int runtime_ms()
+{
+ return msTime() - msStart;
+}
+
+unsigned long int runtime()
+{
+ return (runtime_ms() + 499) / 1000;
+}
+
+char testStartTime[16];
+
+GtkWidget* startWidget = 0;
+GtkWidget* ptfWidget = 0;
+
+char test_name[64];
+extern void page_stress_set_report_name(void);
+
+const char* page_main_test_name()
+{
+ if (test_name[0]) return test_name;
+ return 0;
+}
+
+static char*
+page_main_format_date(char* date, bool startTime)
+{
+ time_t aclock;
+ time(&aclock); /* Get time in seconds */
+ struct tm* t = localtime(&aclock); /* Convert time to struct tm form */
+
+ sprintf(date, "%02d:%02d %04d/%02d/%02d",
+ t->tm_hour, t->tm_min,
+ t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
+
+ if (startTime)
+ {
+ sprintf(testStartTime, "%02d:%02d", t->tm_hour, t->tm_min);
+ sprintf(test_name, "%02d%02d", t->tm_hour, t->tm_min);
+ page_stress_set_report_name();
+ }
+}
+
+static char previousTestTime[32];
+
+const char* nmea_epoch();
+
+void
+page_main_stop(const char* err)
+{
+ const char* msg = "";
+ if (err)
+ {
+ msg = "error: ";
+ NMEA_MSG(err);
+ }
+ else
+ {
+ err = "successfully";
+ }
+ agps_cb_stop();
+
+ gtk_button_set_label(GTK_BUTTON(startWidget), "Power on");
+ gllinRunning = false;
+ gtk_widget_set_sensitive(ptfWidget, true);
+
+ char date[32];
+ page_main_format_date(date, false);
+
+ char buf[2048];
+ sprintf(buf, "Stopped gllin %s%s\n"
+ "at %s\n"
+ "run time %d seconds\n"
+ "Previous test data\n%s\n",
+ msg, err, date, runtime(),
+ nmea_epoch());
+ NMEA_MSG(buf);
+}
+
+//------------------------------------------------------------------------------
+//
+// on_clicked_start()
+//
+// Start or stop the GLLIN.
+//
+//------------------------------------------------------------------------------
+
+extern void page_stress_set_report_name(void);
+extern void page_pm_batch_done();
+
+void on_clicked_start(GtkWidget* widget, gpointer data)
+{
+ widget = startWidget;
+ const char* err;
+
+ char buf[128];
+
+
+ g_print("START button. GLLIN %srunning\n", (gllinRunning) ? "" : "not ");
+ testStartTime[0] = 0;
+
+ if (gllinRunning)
+ {
+ gllin_stop();
+ page_pm_batch_done();
+ return;
+ }
+
+ err = gllin_detect();
+ if (err)
+ {
+ g_print("gllin_detect %s\n", err);
+ NMEA_MSG(err);
+ return;
+ }
+
+ doing_ptf = GPOINTER_TO_INT(data);
+ err = gllin_start();
+ if (err)
+ {
+ NMEA_MSG(err);
+ return;
+ }
+
+ gllinRunning = true;
+
+ clearStats();
+ page_stress_set_report_name();
+ page_main_format_date(previousTestTime, true);
+ sprintf(buf, "Started GPS%s%s%s\nat %s\n",
+ (doing_ptf) ? " one fix" : " periodic",
+ (doing_batch) ? " (batch)" : "",
+ (doing_stress) ? " (stress)" : "",
+ previousTestTime);
+ NMEA_MSG(buf);
+ agps_cb_start(0);
+ page_pm_batch_start();
+ gtk_button_set_label(GTK_BUTTON(widget), "Power off");
+ gtk_widget_set_sensitive(ptfWidget, false);
+}
+
+void
+page_main_done()
+{
+ // Nothing to do at the end of the NMEA epoch?
+ // Might be nice to rotate a little roundel or blink an LED, etc.
+ // But then we should put it on all pages....
+}
+
+#if 0 // Only for stress test future feature.
+
+// "queue up" the need to stop for polling by the main GTK thread
+// This is to prevent the need to thread-protect everything.
+//
+// Caution: called from a timer thread, so all called GTK+ widgets
+// must be protected by gdk_threads_enter() and gdk_threads_leave()
+
+static bool need_to_stop = false;
+
+void
+page_main_schedule_stop()
+{
+ need_to_stop = true;
+}
+
+void
+page_main_poll_for_stop()
+{
+ if (!need_to_stop) return;
+ need_to_stop = false;
+ const char* msg = "stopped";
+ if (gllinRunning)
+ {
+ msg = "stopping...";
+ on_clicked_start(0, 0);
+ }
+ page_stress_msg(msg);
+}
+
+// Stress test calls here to start/stop the GLLIN.
+//
+// Caution: called from a timer thread, so all called GTK+ widgets
+// must be protected by gdk_threads_enter() and gdk_threads_leave()
+
+void
+page_main_gllin(bool start)
+{
+ const char* msg = "";
+ if (start)
+ {
+ if (gllinRunning)
+ {
+ msg = "Running";
+ }
+ else
+ {
+ msg = "starting...";
+ on_clicked_start(0, 0);
+ }
+ }
+ else
+ {
+ msg = "stopping...";
+ page_main_schedule_stop();
+ page_main_poll_for_stop(); // remove if g_timeout cb needs mutex
+ }
+ page_stress_msg(msg);
+}
+
+#endif
+
+void on_clicked_exit(GtkWidget* widget, gpointer data)
+{
+ g_print("EXIT button\n");
+ agps_stop();
+ gtk_main_quit();
+}
+
+void on_clicked_reset(GtkWidget* widget, gpointer data)
+{
+ char c = GPOINTER_TO_INT(data);
+
+ //printf("performing %c reset\n", c);
+
+ clearStats();
+ gllin_reset(c);
+}
+
+static gboolean
+expose_main_event(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("MN");
+ return FALSE;
+}
+
+GtkWidget*
+page_main_create(GtkWidget* window)
+{
+ GtkWidget* label;
+ GtkWidget* button2;
+ GtkWidget* vbox;
+ GtkWidget* table;
+
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ table = gtk_table_new(14, 2, TRUE);
+ gtk_signal_connect(GTK_OBJECT(table), "expose_event",
+ G_CALLBACK(expose_main_event), table);
+
+ //--------------------------------------------------------------------------
+ // label
+ //--------------------------------------------------------------------------
+ label = gtk_label_new(page_main_omgui_version());
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 0, 1);
+ gtk_widget_show(label);
+
+ //--------------------------------------------------------------------------
+ // label
+ //
+ // All text from the "main" page goes to this agpsLabel
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Press START to begin GPS");
+ agpsLabel = GTK_LABEL(label);
+ gtk_label_set_justify(agpsLabel, GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 1, 13);
+ gtk_widget_show(label);
+
+ {
+ GtkWidget *box, *button;
+
+ box = gtk_hbox_new (FALSE, 0);
+
+ button = gtk_button_new_with_label("Cold reset");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_reset), GINT_TO_POINTER('c'));
+ gtk_box_pack_start_defaults(GTK_BOX(box), button);
+
+ button = gtk_button_new_with_label("Warm reset");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_reset), GINT_TO_POINTER('w'));
+ gtk_box_pack_start_defaults(GTK_BOX(box), button);
+
+ button = gtk_button_new_with_label("Hot reset");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_reset), GINT_TO_POINTER('h'));
+ gtk_box_pack_start_defaults(GTK_BOX(box), button);
+
+ gtk_widget_show_all(box);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 2, 12, 13);
+ }
+ //--------------------------------------------------------------------------
+ // range controls
+ //--------------------------------------------------------------------------
+ create_range_controls(window, table, false);
+
+ //--------------------------------------------------------------------------
+ // box for all the buttons
+ //--------------------------------------------------------------------------
+ GtkWidget* box = gtk_hbox_new (FALSE, 0);
+
+ //--------------------------------------------------------------------------
+ // start periodic button
+ //--------------------------------------------------------------------------
+ GtkWidget* button = gtk_button_new_with_label("Power on");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_start), GINT_TO_POINTER(0));
+ gtk_widget_show(button);
+ startWidget = button;
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+
+ //--------------------------------------------------------------------------
+ // PTF button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("One Fix");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_start), GINT_TO_POINTER(1));
+ gtk_widget_show(button);
+ ptfWidget = button;
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+
+ //--------------------------------------------------------------------------
+ // exit button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("Exit");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_exit), NULL);
+ gtk_widget_show(button);
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 2, 13, 14);
+ gtk_widget_show(box);
+
+ gtk_widget_show(table);
+ return table;
+ test_name[0] = 0;
+}
+
+extern void pm_report(FILE* f, bool stress);
+
+void
+page_main_report(FILE* f)
+{
+ fprintf(f, "GPS is %s\n", (gllinRunning) ? "Running": "Stopped");
+ pm_report(f, false);
+ fprintf(f, "%s\n", gtk_label_get_text(agpsLabel));
+}
Added: developers/olv/openmoko-agpsui2/src/page_map.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_map.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_map.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,1687 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "agps.h"
+#include "sv_bar.h"
+
+// #define OPT_TEST_AVERAGE
+#undef OPT_TEST_AVERAGE
+
+#undef DEBUG_PAGE_MAP
+
+#ifdef OPT_TEST_AVERAGE
+#define DEBUG_PAGE_MAP
+#endif
+
+static GtkAdjustment* adj_center;
+static GtkButton* button_style;
+static GtkWidget* scale_center;
+
+static int adj_upper = 0;
+static int adj_lower = 1;
+
+static void haveNewPosition(int n);
+
+//------------------------------------------------------------------------------------
+//
+// page_map.cpp
+//
+// Plot the GPS positions in a window.
+// Follow the first, last, and average position.
+// Valid for -88 to +88 degrees.
+//
+//------------------------------------------------------------------------------------
+
+class lla;
+const double PI = 3.1415926535;
+static double pixels_per_meter;
+static void MAP_draw_position(lla* p, bool suppress = true);
+static void MAP_recompute_xy_pixels(const char* msg);
+void page_MAP_init();
+static void MAP_draw_avg_circle(lla* p);
+GtkLabel* map_label;
+extern int fix_good;
+
+static GdkGC* blue_gc = 0;
+static GdkGC* grey_gc = 0;
+
+static GtkDrawingArea* MAP;
+static GdkPixmap* MAP_PIX = 0;
+bool mph = false;
+static PangoLayout* MAP_text;
+
+// KLUDGE for A3 or larger fonts only:
+// bool large_font = true;
+// bool a3_hardware = true;
+#define large_font 1
+#define a3_hardware 1
+
+extern GdkGC* alloc_color(GdkPixmap* pm, const char* color);
+extern void notebook_expose(const char* pageName);
+static double meter_scale();
+void scale_init(GtkScale* scale);
+static void MAP_draw_all_points();
+void page_MAP_alloc_colors();
+static void MAP_redraw();
+static void MAP_draw_lla();
+void page_MAP_have_lla(double lon, double lat, int alt, int heading, int speed, int time);
+static void MAP_draw_scale(double mult, int meters, int nDividers);
+
+static bool map_have_new_pos = false;
+
+static int lla_x0;
+static int lla_y0;
+
+#define MAX_X ((1 << 15) - 1)
+#define MIN_X (-MAX_X)
+#define MAX_Y MAX_X
+#define MIN_Y MIN_X
+#define SCREEN_WIDTH 476
+#define SCREEN_HEIGHT 400
+
+
+//------------------------------------------------------------------------------------
+//
+// Class lla
+//
+// Save the longitude and latitude.
+// (the altitude, heading, speed, time are also saved).
+// Convert LLA one time to meters.
+// Convert to an integer pixel offset from the previous point when
+// the map scale changes.
+//
+//------------------------------------------------------------------------------------
+
+class lla
+{
+public:
+ lla() : time(0)
+ {
+ };
+
+ lla(double lon_, double lat_, int alt_, int head, int sp_, unsigned long t_)
+ :
+ lon(lon_),
+ lat(lat_),
+ alt(alt_),
+ heading(head),
+ speed(sp_),
+ time(t_)
+ {
+ };
+
+ void init(double lon_, double lat_, int alt_, int head, int sp_, unsigned long t_)
+ {
+ lon = lon_;
+ lat = lat_;
+ alt = alt_;
+ heading = head;
+ speed = sp_;
+ time = t_;
+ compute_xy_meters();
+ last = *this;
+ };
+
+ ~lla()
+ {
+ };
+
+ void compute_xy_meters(void);
+ void compute_xy_meters_abs(lla* p);
+ void compute_xy_pixels(const char* msg = 0);
+
+ double lon;
+ double lat;
+ double delta_lon;
+ double delta_lat;
+
+ double meters_x; // relative to previous point.
+ double meters_y; // relative to previous point.
+
+ int pixels_x; // relative to previous point.
+ int pixels_y;
+
+ int alt; // meters
+ int heading; // 0=N 90=E 180=S 270=W
+ int speed; // km/h
+ unsigned long time; // ms into the GPS week.
+
+ static void restart(void)
+ {
+ prev = 0;
+ }
+ static lla first;
+
+ static lla* lastPoint()
+ {
+ return &last;
+ };
+
+private:
+ static lla* prev;
+ static lla last;
+};
+
+#ifdef DEBUG_PAGE_MAP
+// #define DEBUG_F(f) printf(" " #f " %f\n", f)
+#define DEBUG_F(f)
+#else
+#define DEBUG_F(f)
+#endif
+
+enum
+{
+#ifdef OPT_TEST_AVERAGE
+ MAX_LLA = 7
+#else
+ MAX_LLA = 2000
+#endif
+};
+
+lla avg_lla;
+lla LLA[MAX_LLA];
+static int nLLA = 0;
+static int indexLLA = 0;
+
+static double sum_lon;
+static double sum_lat;
+// static int sum_alt = 0;
+
+lla lla::last;
+lla lla::first;
+lla* lla::prev = 0;
+
+void lla::compute_xy_meters()
+{
+ if (prev)
+ {
+ compute_xy_meters_abs(prev);
+ }
+ else
+ {
+ compute_xy_meters_abs(this);
+ first = *this;
+ }
+ last = *this;
+ prev = this;
+}
+
+//------------------------------------------------------------------------------------
+//
+// Class MeterScale
+//
+// Here are all the choices of what you can select with the +/- buttons.
+//
+//------------------------------------------------------------------------------------
+
+struct MeterScale
+{
+ enum
+ {
+ SCALE_1x1 = 9
+ };
+ double scale; // Pixels/meter
+ int ruler_meters;
+ int ruler_dividers;
+ const char* name;
+};
+
+MeterScale scales[] =
+{
+ { 50, 2, 2, "x50" }, // 0
+ { 32, 5, 5, "x32" },
+ { 20, 5, 5, "x20" },
+ { 16, 10, 5, "x16" },
+
+ { 10, 10, 5, "x10" }, // 4
+ { 8, 20, 4, "x8" },
+
+ { 5, 20, 4, "x5" }, // 6
+ { 4, 20, 4, "x4" },
+ { 2, 50, 5, "x2" },
+
+ { 1.0, 100, 5, "x1" }, // 9
+
+ { 0.5, 200, 4, "/2" }, // 10
+ { .2, 500, 5, "/5" },
+ { .1, 1000, 5, "/10" },
+
+ { .05, 2000, 4, "/20" }, // 13
+ { .02, 5000, 5, "/50" },
+ { .01, 10000, 5, "/100" },
+
+ { .005, 20000, 5, "/200" }, // 16
+ { .002, 50000, 5, "/500" },
+ { .001, 100000, 5, "/1k" },
+
+ { .0005, 200000, 4, "/2k" }, // 19
+ { .0002, 500000, 5, "/5k" }
+};
+#define MAX_SCALES (sizeof(scales) / sizeof(*scales))
+
+static int scale_index = MeterScale::SCALE_1x1;
+
+//-------------------------------------------------------------------------------------
+//
+// testAverage()
+//
+//-------------------------------------------------------------------------------------
+
+#ifdef OPT_TEST_AVERAGE
+static bool
+testAverage()
+{
+ static bool average_done = false;
+ static bool been_here = false;
+
+ if (been_here) return average_done;
+ been_here = true;
+
+ page_MAP_have_lla(0.000010, 0.000010, 50, 12, 13, 12351);
+ page_MAP_have_lla(0.000020, 0.000020, 50, 12, 13, 12352);
+ page_MAP_have_lla(0.000030, 0.000030, 50, 12, 13, 12353); // Average/5
+ page_MAP_have_lla(0.000040, 0.000040, 50, 12, 13, 12354);
+ page_MAP_have_lla(0.000050, 0.000050, 50, 12, 13, 12355);
+
+ page_MAP_have_lla(0.000210, 0.000290, 50, 12, 13, 12356);
+ page_MAP_have_lla(0.000220, 0.000280, 50, 12, 13, 12357);
+ page_MAP_have_lla(0.000250, 0.000250, 50, 12, 13, 12358); // Average/5
+ page_MAP_have_lla(0.000280, 0.000220, 50, 12, 13, 12359);
+ page_MAP_have_lla(0.000290, 0.000210, 50, 12, 13, 12360);
+
+ average_done = true;
+ return average_done;
+}
+
+#define TEST_AVERAGE() testAverage()
+// #define TEST_AVERAGE()
+#else
+#define TEST_AVERAGE() false
+#endif
+
+//------------------------------------------------------------------------------
+//
+// IMPORTANT NOTE:
+//
+// This code is intended ONLY to show relative positions
+// of lat/lon on an x,y pixmap to look for GPS problems.
+// It is NOT to be used for any accurate mapping
+// to reference points, reference to any geoid, or any
+// form of navigation.
+//
+//------------------------------------------------------------------------------
+
+void lla::compute_xy_meters_abs(lla* p)
+{
+#ifdef DEBUG_PAGE_MAP
+ printf("compute_xy_meters[%f %f]-[%f %f]", lon, lat, p->lon, p->lat);
+#endif
+
+ double average_lat = (p->lat + lat)/2.0; DEBUG_F(average_lat);
+ double rad_lat = average_lat * PI / 180.0; DEBUG_F(rad_lat);
+
+ double m = 111132.09; DEBUG_F(m);
+ m -= 566.05 * cos(2.0 * rad_lat); DEBUG_F(m);
+ m += 1.2*cos(4*rad_lat); DEBUG_F(m);
+
+ delta_lat = lat - p->lat; DEBUG_F(delta_lat);
+ meters_y = delta_lat * m; DEBUG_F(meters_y);
+
+ double pp = 111415.13 * cos(rad_lat) - 94.55*cos(3*rad_lat); DEBUG_F(pp);
+ delta_lon = lon - p->lon; DEBUG_F(delta_lon);
+ if (delta_lon <= -180.0)
+ {
+ delta_lon += 360.0; // printf("#%f#", delta_lon);
+ }
+ else if (delta_lon > 180.0)
+ {
+ delta_lon -= 360.0; // printf("$%f$", delta_lon);
+ }
+ meters_x = delta_lon * pp; DEBUG_F(meters_x);
+
+#ifdef DEBUG_PAGE_MAP
+ printf("= [%f %f] ", delta_lon, delta_lat);
+ printf("= {%f %f}m\n", meters_x, meters_y );
+#endif
+}
+
+void
+lla::compute_xy_pixels(const char* msg)
+{
+ // The negative sign on the Y represents the GTK+ coordinate system
+ // where X increases to the right and Y increases as you go lower
+ // on the screen.
+ pixels_x = static_cast<int> (pixels_per_meter * meters_x);
+ pixels_y = -static_cast<int> (pixels_per_meter * meters_y);
+#ifdef DEBUG_PAGE_MAP
+ if (msg)
+ {
+ printf("compute_xy_pixels(%s) (%d %d) = %f x {%f %f}\n",
+ msg,
+ pixels_x, pixels_y, pixels_per_meter,
+ meters_x, meters_y);
+ }
+#endif
+}
+
+static void
+printLLA()
+{
+}
+
+static lla*
+addLLA()
+{
+ int old_n = nLLA;
+ lla* result = LLA + indexLLA;
+ if (++indexLLA >= MAX_LLA) indexLLA = 0;
+
+ if (++nLLA > MAX_LLA)
+ {
+ nLLA = MAX_LLA; // Limit ourselves to our LLA array size.
+ sum_lon -= result->lon; // The average is over what we have in
+ sum_lat -= result->lat; // the array, so remove older items from
+ // sum_alt -= result->alt; // the running average.
+#ifdef DEBUG_PAGE_MAP
+ printf("SUB [%f %f]\n", result->lon, result->lat);
+#endif
+ // Since we're about to wipe out this item, make sure the *next*
+ // item is still tracked relative to the initial position.
+ // To keep it simple, reassign the initial position to be the next
+ // position:
+
+ lla* next = LLA + indexLLA;
+ next->meters_x = 0;
+ next->meters_y = 0;
+ next->delta_lon = 0;
+ next->delta_lat = 0;
+ lla::first = *next;
+ }
+
+#ifdef DEBUG_PAGE_MAP
+ printf("have_LLA %d --> %d %d\n", old_n, nLLA, fix_good);
+#endif
+ haveNewPosition(fix_good);
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+//
+// lla iterator
+//
+// OpenMoko apparently lacks <deque> and <algorithm>, so here is a hacked-version
+// of some iterators for the lla{} vector.
+//
+//------------------------------------------------------------------------------
+
+static lla* pEnd;
+static lla* pCur;
+static lla* pWrap = LLA + MAX_LLA;
+
+lla* lla_next()
+{
+ if (++pCur >= pWrap)
+ {
+ pCur = LLA;
+ }
+ return pCur;
+}
+
+lla* lla_pointN(int n)
+{
+ int i = n;
+ if (nLLA >= MAX_LLA) i = (indexLLA + i) % MAX_LLA;
+
+ lla* r = LLA + i;
+#ifdef DEBUG_PAGE_MAP
+ printf("lla_pointN(%d) LLA[%d]=[%f %f]\n", n, i, r->lon, r->lat);
+#endif
+ return r;
+}
+
+bool lla_last()
+{
+ return (pCur == pEnd);
+}
+
+lla* lla_begin()
+{
+ if (!nLLA) return 0;
+ pCur = LLA;
+ pEnd = LLA + indexLLA;
+ if (nLLA >= MAX_LLA)
+ {
+ pCur = LLA + indexLLA;
+ pEnd = pCur;
+ // if (++pCur >= pWrap)
+ if (pCur >= pWrap)
+ {
+ pCur = LLA;
+ }
+ }
+ return pCur;
+}
+
+//------------------------------------------------------------------------------
+//
+// Class TrackStyle
+//
+// Follow the first, average, or last position.
+//
+//------------------------------------------------------------------------------
+
+class TrackStyle
+{
+public:
+ enum TrackStyleEnum
+ {
+ POINT_0 = 0,
+ AVERAGE,
+ POINT_N,
+ POINT_LAST,
+ STYLE_MAX
+ };
+
+ static bool increment(void);
+ static const char* getName(char* buf);
+ static const char* getLabel(void);
+ static lla* getReference(void);
+ static lla* getReference(TrackStyleEnum style);
+ static TrackStyleEnum getStyle(void);
+ static bool NewPositionCenter(int i);
+
+ TrackStyleEnum style;
+ const char* label;
+ const char* name;
+
+private:
+ static TrackStyle styles[STYLE_MAX];
+ static int index;
+ static int point_n;
+ static lla* reference_position;
+};
+
+static lla lla_n; // the Nth point.
+
+lla*
+TrackStyle::getReference(TrackStyleEnum i)
+{
+ lla* r = 0;
+ switch (i)
+ {
+ default:
+ case POINT_0:
+ break;
+ case AVERAGE:
+ r = &avg_lla;
+ break;
+ case POINT_N:
+ // Convert the intuitive, user-based index that starts at 1.
+ // into internal point index "point_n" which is 0-based
+ lla_n = *lla_pointN(point_n-1);
+ r = &lla_n;
+ break;
+ case POINT_LAST:
+ r = lla::lastPoint();
+ break;
+ }
+ return r;
+}
+
+lla*
+TrackStyle::getReference(void)
+{
+ return getReference(styles[index].style);
+}
+
+int TrackStyle::index = TrackStyle::AVERAGE; // Default tracking style
+lla* TrackStyle::reference_position = 0;
+int TrackStyle::point_n;
+
+TrackStyle::TrackStyleEnum TrackStyle::getStyle()
+{
+ return styles[index].style;
+}
+
+TrackStyle TrackStyle::styles[TrackStyle::STYLE_MAX] =
+{
+ {TrackStyle::POINT_0, "First","First Fix"},
+ {TrackStyle::AVERAGE, "Avg", "Average" },
+ {TrackStyle::POINT_N, "Fix", "Fix #%d" },
+ {TrackStyle::POINT_LAST, "Last", "Last Fix" }
+};
+
+static void
+haveNewPosition(int n)
+{
+ adj_upper = n;
+ const char* msg = 0;
+ if (TrackStyle::getStyle() == TrackStyle::POINT_LAST)
+ {
+ msg = "value";
+ }
+ g_object_set(G_OBJECT(adj_center),
+ "upper", (gdouble) n,
+ msg, (gdouble) n,
+ 0);
+ gtk_adjustment_changed(adj_center);
+ if (msg)
+ {
+ gtk_adjustment_value_changed(adj_center);
+ }
+ if (n > MAX_LLA)
+ {
+ //------------------------------------------------
+ //
+ // The LLA array is full, and we've wrapped around.
+ // So the user will see numbers larger, but internally,
+ // we have to map them as shown:
+ // AVERAGE FIRST LAST
+ // user: n-MAX_LLA-1 n-MAX_LLA n
+ // LLA[] 0 1 MAX_LLA
+ //
+ //------------------------------------------------
+
+ adj_lower = n - MAX_LLA;
+ g_object_set(G_OBJECT(adj_center), "lower", (gdouble) adj_lower, 0);
+ }
+}
+
+const char* TrackStyle::getLabel(void)
+{
+ return styles[index].label;
+}
+
+const char* TrackStyle::getName(char* buf)
+{
+ sprintf(buf, styles[index].name, point_n);
+ return buf;
+}
+
+bool TrackStyle::increment(void)
+{
+ if (++index >= STYLE_MAX)
+ {
+ index = POINT_0;
+ }
+ return (index == POINT_N);
+}
+
+bool
+TrackStyle::NewPositionCenter(int adj)
+{
+ bool rc = true;
+
+ if (adj == point_n)
+ {
+ // No change, so this is a self-induced jump!
+ printf("NewPositionCenter(%d) no change\n", adj);
+ return rc;
+ }
+
+ lla* p = lla_pointN(adj - 1);
+
+ // Moved to the 1st position, so just go there directly.
+ if (lla_begin() == p)
+ {
+ point_n = adj;
+ printf("NewPositionCenter(%d) first\n", adj);
+ return rc;
+ }
+
+ int new_adj = adj;
+ if (adj < point_n) // go backwards, but don't go past the start.
+ {
+ int lower_limit = fix_good - MAX_LLA;
+ if (lower_limit < 0) lower_limit = 1;
+
+ // Since we're going backwards, look in the *NEXT* position
+ // to see if we have a position change.
+ p = lla_pointN(new_adj);
+
+ while (p->pixels_x == 0 && p->pixels_y == 0)
+ {
+ --new_adj;
+ if (new_adj < lower_limit)
+ {
+ printf("NewPositionCenter(%d) first %d\n", adj, new_adj);
+ rc = false;
+ }
+ p = lla_pointN(new_adj);
+ }
+ }
+ else // go forwards, but don't go past the end.
+ {
+ while (p->pixels_x == 0 && p->pixels_y == 0)
+ {
+ ++new_adj;
+ if (new_adj > fix_good)
+ {
+ printf("NewPositionCenter(%d) last %d\n", adj, new_adj);
+ return false;
+ }
+ p = lla_pointN(new_adj - 1);
+ }
+ }
+
+ point_n = new_adj;
+ if (new_adj != adj) rc = false;
+
+ if (!rc)
+ {
+ // Since we're skipping points, don't
+ // update now: expect to be called to do the update.
+ g_object_set(G_OBJECT(adj_center), "value", (gdouble) new_adj, 0);
+ gtk_adjustment_value_changed(adj_center);
+ printf("NewPositionCenter(%d) skip to %d\n", adj, new_adj);
+ }
+ return rc;
+}
+
+static int pixel_offset_x;
+static int pixel_offset_y;
+
+static void
+centerOfWindow(int& x, int& y)
+{
+ const int screen_center_x = 476/2;
+ const int screen_center_y = 400/2;
+
+ x = screen_center_x;
+ y = screen_center_y;
+}
+
+const char*
+formatLL(double lon, double lat)
+{
+ char ew = 'E';
+ char ns = 'N';
+
+ if (lon < 0.0) ew = 'W';
+ if (lat < 0.0) ns = 'S';
+
+ static char buf[64];
+ sprintf(buf, "%f %c %f %c", lon, ew, lat, ns);
+ return buf;
+}
+
+//-----------------------------------------------------------------------------------
+//
+// computePixelBaseline()
+//
+// The pixel baseline is added to each pixels_x,pixels_y of the lla{}.
+// It is:
+// a) position[0] (or 0,0) + "screen center"
+// When the center is the first position fix.
+// b) position[0]-avg + "screen center"
+// When the center is the average position.
+// c) position[0]-position[LAST] + "screen center"
+// When the center is the last position.
+// d) position[0]-position[n] + "screen center"
+// When the center is the position[n].
+//
+// Since position[N].meters_x and .pixels_x are computed relative
+// to position[N-1], we need to compute a temporary:
+// temp_lla = position[N] - position[0]
+//
+//-----------------------------------------------------------------------------------
+
+void
+computePixelBaseline()
+{
+ centerOfWindow(pixel_offset_x, pixel_offset_y);
+
+ lla* r = TrackStyle::getReference();
+
+ //-----------------------------------------------------------------
+ // If we have a relative lla to use, then figure out how far it is
+ // from [0,0].
+ //-----------------------------------------------------------------
+
+ if (r)
+ {
+ char buf0[64];
+ const char* n = TrackStyle::getName(buf0);
+
+ r->compute_xy_meters_abs(&lla::first);
+ r->compute_xy_pixels(n);
+#ifdef DEBUG_PAGE_MAP
+ printf("baseline (%s)-first = (%d %d) - (%d %d) = (%d %d)\n",
+ buf0,
+ pixel_offset_x, pixel_offset_y,
+ r->pixels_x, r->pixels_y,
+ pixel_offset_x - r->pixels_x,
+ pixel_offset_y - r->pixels_y);
+#endif
+ pixel_offset_x -= r->pixels_x;
+ pixel_offset_y -= r->pixels_y;
+ }
+ else
+ {
+ // printf("baseline FIRST = (%d %d)\n", pixel_offset_x, pixel_offset_y);
+ }
+ if (r != &avg_lla)
+ {
+ // printf("redo(avg) ");
+ avg_lla.compute_xy_meters_abs(&lla::first);
+ avg_lla.compute_xy_pixels("redo(avg)");
+ }
+}
+
+//-----------------------------------------------------------------------------------
+//
+// set_fix_label()
+//
+//-----------------------------------------------------------------------------------
+
+static void
+set_fix_label()
+{
+ lla* p = TrackStyle::getReference();
+ if (!p) p = &lla::first;
+
+ char buf0[64];
+ char buf1[128];
+ sprintf(buf1, "%s %s #%d",
+ TrackStyle::getName(buf0),
+ formatLL(p->lon, p->lat),
+ fix_good);
+ gtk_label_set_text(map_label, buf1);
+}
+
+//-----------------------------------------------------------------------------------
+//
+// page_MAP_have_lla()
+//
+// nmea.cpp sends us positions when they arrive from the NMEA input.
+// Create an lla & save it.
+//
+//-----------------------------------------------------------------------------------
+
+void
+page_MAP_have_lla( double lon, double lat,
+ int alt,
+ int heading, int speed, int time)
+{
+ if (TEST_AVERAGE()) return;
+
+#ifdef DEBUG_PAGE_MAP
+ printf("page_MAP_have_lla [%f %f]\n", lon, lat);
+#endif
+
+ lla* p = addLLA();
+ p->init(lon, lat, alt, heading, speed, time);
+
+ bool allowSuppress = true;
+ if (nLLA == 1)
+ {
+ allowSuppress = false;
+ sum_lon = lon;
+ sum_lat = lat;
+ }
+ else
+ {
+ sum_lon += p->lon;
+ sum_lat += p->lat;
+ }
+
+#ifdef DEBUG_PAGE_MAP
+ printf("ADD [%f %f] = \n", p->lon, p->lat);
+ printf("sum [%f %f] / %d\n", sum_lon, sum_lat, nLLA);
+#endif
+
+ // Compute the average position:
+ avg_lla.lon = sum_lon / (double) nLLA;
+ if (avg_lla.lon > 180.0) avg_lla.lon -= 360.0;
+ else if (avg_lla.lon <= -180.0) avg_lla.lon += 360.0;
+
+ avg_lla.lat = sum_lat / (double) nLLA;
+ // avg_lla.alt = (sum_alt + nLLA/2) / nLLA;
+
+#ifdef DEBUG_PAGE_MAP
+ printf("avg [%f %f]\n", avg_lla.lon, avg_lla.lat);
+#endif
+
+ map_have_new_pos = true;
+
+ // Only compute pixel baseline if:
+ // ... mult changes
+ // ===> or if average changes (when centering on the average) <===
+ // ===> or if newer position (when centering on the last position) <===
+ // ===> or if newer position (when we have filled the LLA array ) <===
+ computePixelBaseline();
+ p->compute_xy_pixels("new lla");
+
+ if (MAP_PIX)
+ {
+ MAP_draw_avg_circle(&avg_lla); // average is a small circle
+ MAP_draw_position(p, allowSuppress);
+ set_fix_label();
+ }
+}
+
+//------------------------------------------------------------------------------------
+//
+// MAP_self_test
+//
+// Create dummy points to exercise the plotting algorithms
+//
+//------------------------------------------------------------------------------------
+
+static const char*
+MAP_self_test()
+{
+ const char* msg = 0;
+
+ // Stub for now: add some data points!
+ static bool been_here = false;
+ if (!been_here)
+ {
+ been_here = true;
+
+#if 0 // PASS
+ msg = "2-point test case";
+ page_MAP_have_lla(-1.0, -1.0, 50, 0, 0, 126000);
+ page_MAP_have_lla( 1.0, 1.0, 50, 0, 0, 127000);
+#if 0 // PASS
+ msg = "3-point test case";
+ page_MAP_have_lla( 1.1, 1.0, 50, 0, 0, 127000);
+#endif
+#endif
+
+#if 0 // PASS
+ msg = "Local test case";
+ page_MAP_have_lla(-121.000000, 37.000000, 50, 0, 0, 123000);
+ page_MAP_have_lla(-121.000120, 37.000000, 50, 0, 0, 124000);
+ page_MAP_have_lla(-121.000120, 37.001500, 50, 0, 0, 125000);
+ page_MAP_have_lla(-121.000000, 37.001500, 50, 0, 0, 126000);
+ page_MAP_have_lla(-121.000000, 37.000200, 50, 0, 0, 127000);
+#endif
+
+#if 0 // PASS
+ msg = "West test case";
+ page_MAP_have_lla( 0.000030, -0.00050, 50, 0, 0, 123000);
+ page_MAP_have_lla(-0.000120, -0.00050, 50, 0, 0, 124000);
+ page_MAP_have_lla(-0.000120, 0.00050, 50, 0, 0, 125000);
+ page_MAP_have_lla( 0.000030, 0.00050, 50, 0, 0, 126000);
+ page_MAP_have_lla( 0.000030, -0.00045, 50, 0, 0, 127000);
+#endif
+
+#if 0 // PASS // Test case 1 (wrap around "east pole" 180,0)
+ msg = "East #1 test case";
+ page_MAP_have_lla(-179.99801, -0.000511, 50, 0, 0, 123000);
+ page_MAP_have_lla( 179.99812, -0.000522, 50, 0, 0, 124000);
+ // page_MAP_have_lla(-179.99803, -0.000536, 50, 0, 0, 123000);
+
+#if 0
+ msg = "East #2 test case";
+ page_MAP_have_lla( 179.99813, +0.00053, 50, 0, 0, 125000);
+ page_MAP_have_lla(-179.99794, +0.00054, 50, 0, 0, 126000);
+ page_MAP_have_lla(-179.99805, -0.00050, 50, 0, 0, 127000);
+#endif
+#endif
+
+#if 0 // FAIL // Test case 1 (wrap around "north pole" 0,90)
+ msg = "North test case\n";
+ page_MAP_have_lla( 0.00101, 89.99500, 50, 0, 0, 123000);
+ page_MAP_have_lla( 90.00102, 89.99500, 50, 0, 0, 124000);
+ page_MAP_have_lla( 179.00103, 89.99500, 50, 0, 0, 125000);
+ page_MAP_have_lla( -90.00104, 89.99500, 50, 0, 0, 126000);
+ page_MAP_have_lla( -0.99905, 89.99450, 50, 0, 0, 127000);
+#endif
+
+#if 0 // FAIL // Test case 1 (wrap around "south pole" 0,-90)
+ msg = "South test case\n";
+ page_MAP_have_lla( 0.00100, -89.99500, 50, 0, 0, 123000);
+ page_MAP_have_lla( 90.00100, -89.99500, 50, 0, 0, 124000);
+ page_MAP_have_lla( 179.00100, -89.99500, 50, 0, 0, 125000);
+ page_MAP_have_lla( -90.00100, -89.99500, 50, 0, 0, 126000);
+ page_MAP_have_lla( -0.99900, -89.99450, 50, 0, 0, 127000);
+#endif
+
+ }
+ return msg;
+}
+
+//-----------------------------------------------------------------------------------
+//
+// cb_change_center()
+//
+// Adjusting slider to change center position
+//
+//-----------------------------------------------------------------------------------
+
+static void
+cb_change_center(GtkAdjustment* adj)
+{
+ if (TrackStyle::NewPositionCenter((gint) adj->value))
+ {
+ MAP_redraw();
+ }
+}
+
+//-----------------------------------------------------------------------------------
+//
+// on_map_units_change()
+//
+// Do nothing (maybe self-test)
+// Update the page label.
+//
+//-----------------------------------------------------------------------------------
+
+static void
+on_map_units_change()
+{
+ // page_MAP_init();
+ const char* msg = MAP_self_test();
+ if (!msg)
+ {
+ msg = "km/h";
+ if (mph) msg = "mph";
+ }
+ gtk_label_set_text(map_label, msg);
+}
+
+//------------------------------------------------------------------------------
+//
+// on_clicked_track_style()
+//
+// Walk through the different tracking styles.
+//
+//------------------------------------------------------------------------------
+
+static void
+on_clicked_track_style(GtkWidget* w, gpointer d)
+{
+ gtk_widget_set_sensitive(GTK_WIDGET(scale_center),
+ TrackStyle::increment() );
+ MAP_recompute_xy_pixels("track style change");
+ MAP_redraw();
+}
+
+//------------------------------------------------------------------------------
+//
+// on_clicked_mph()
+//
+// GTK+ callback.
+// Update the system state, and the button.
+//
+//------------------------------------------------------------------------------
+
+static void
+on_clicked_mph(GtkWidget* widget, gpointer data)
+{
+ mph = !mph;
+ gtk_button_set_label(GTK_BUTTON(data), (mph) ? "mph" : "km/h");
+ on_map_units_change();
+}
+
+static void
+MAP_clear()
+{
+ GtkWidget* w = GTK_WIDGET(MAP);
+ gdk_draw_rectangle(MAP_PIX, w->style->white_gc, TRUE,
+ 0, 0,
+ w->allocation.width,
+ w->allocation.height);
+}
+
+static gboolean
+configure_MAP_event(GtkWidget* w, GdkEventConfigure* event)
+{
+ if (MAP_PIX)
+ {
+ g_object_unref(MAP_PIX);
+ }
+
+ //--------------------------------------------------------------------------
+ // pixmap to make the window easier to draw
+ //--------------------------------------------------------------------------
+ MAP_PIX = gdk_pixmap_new(w->window,
+ w->allocation.width,
+ w->allocation.height, -1);
+ MAP_clear();
+ return TRUE;
+}
+
+static gboolean
+expose_MAP_event(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("MP");
+ GdkRectangle& a = event->area;
+ gdk_draw_drawable(w->window,
+ w->style->fg_gc[GTK_WIDGET_STATE(w)],
+ MAP_PIX, a.x, a.y, a.x, a.y, a.width, a.height);
+ return FALSE;
+}
+
+static GdkGC*
+getGC(bool used)
+{
+ GdkGC* gc = grey_gc;
+ if (used)
+ {
+ gc = blue_gc; // used SV is colored blue
+ }
+ if (!gc)
+ {
+ gc = GTK_WIDGET(MAP)->style->black_gc;
+ }
+ return gc;
+}
+
+void
+page_MAP_alloc_colors()
+{
+ if (!MAP_PIX) return;
+ if (!blue_gc) blue_gc = alloc_color(MAP_PIX, "Blue");
+ if (!grey_gc) grey_gc = alloc_color(MAP_PIX, "SlateGrey");
+}
+
+//------------------------------------------------------------------------------
+//
+// MAP_draw_avg_circle
+//
+// Draw the little "average" circle at the point.
+//
+//------------------------------------------------------------------------------
+
+static void
+MAP_draw_avg_circle(lla* p)
+{
+ int rect = 5;
+
+ int x = pixel_offset_x + p->pixels_x;
+ int y = pixel_offset_y + p->pixels_y;
+
+ if (x > SCREEN_WIDTH || x < 0 || y > SCREEN_HEIGHT || y < 0)
+ {
+ // printf("circle [%f %f] {%f %f} (%d %d) OFF SCREEN\n",
+ // p->lon, p->lat,
+ // p->meters_x, p->meters_y,
+ // x, y);
+ return;
+ }
+
+ //----------------------------------------------
+ // Draw 11x11 circle
+ //----------------------------------------------
+
+ int size = 2*rect + 1;
+#ifdef DEBUG_PAGE_MAP
+ printf("MAP circle (%d %d)==>(%d %d) size %d\n", x, y, x-rect, y-rect, size);
+#endif
+ gdk_draw_arc(MAP_PIX, GTK_WIDGET(MAP)->style->black_gc, FALSE,
+ x - rect, y - rect, size, size, 0, 360 * DEGREE_64);
+}
+
+//-----------------------------------------------------------------------------
+//
+// Draw the positions and lines between them
+//
+// (if they are not too close)
+//
+//-----------------------------------------------------------------------------
+
+static int accum_x;
+static int accum_y;
+
+static void
+MAP_reset_position_accum()
+{
+ accum_x = 0;
+ accum_y = 0;
+}
+
+static void
+MAP_draw_position(lla* p, bool suppress)
+{
+ //------------------------------------------------------
+ // Suppress everything if the point is too close to the
+ // previous position.
+ // The distance is calculated as dx*dx + dy*dy, where
+ // dx == p->pixels_x and
+ // dy == p->pixels_y in meter units.
+ // If we drop a point, then accumulate the delta(x,y) for
+ // the next point.
+ //------------------------------------------------------
+
+ const int rect = 5;
+ const int half_rect_sq = (rect/2) * (rect/2);
+
+ int x = p->pixels_x + accum_x;
+ int y = p->pixels_y + accum_y;
+
+#ifdef DEBUG_PAGE_MAP
+ printf("MAP draw pos (%d %d)", p->pixels_x, p->pixels_y);
+ if (accum_x || accum_y) printf("+(%d %d) ", accum_x, accum_y);
+#endif
+
+ if (suppress)
+ {
+ // We are allowed to suppress this point if the x,y is
+ // too close to the previous point.
+ int dist = x*x + y*y;
+ if (dist < half_rect_sq)
+ {
+#ifdef DEBUG_PAGE_MAP
+ if (dist) printf(" = %d TOO CLOSE: suppress", dist);
+ printf("\n");
+#endif
+ accum_x += p->pixels_x;
+ accum_y += p->pixels_y;
+ return;
+ }
+ }
+
+ x += lla_x0;
+ y += lla_y0;
+
+ MAP_reset_position_accum();
+
+ //----------------------------------------------
+ // The line and position will be grey if it
+ // exceeds bounds;
+ //----------------------------------------------
+
+ GdkGC* gc = getGC(true);
+ if (x > MAX_X || x < MIN_X || y > MAX_Y || y < MIN_Y)
+ {
+ if (x > MAX_X) x = MAX_X;
+ if (x < MIN_X) x = MIN_X;
+ if (y > MAX_Y) y = MAX_Y;
+ if (y < MIN_Y) y = MIN_Y;
+
+#ifdef DEBUG_PAGE_MAP
+ printf(" ==> (%d %d) > %d..%d bounds exceeded ", x, y, MIN_X, MAX_Y);
+#endif
+ gc = getGC(false);
+ }
+
+ //----------------------------------------------
+ // Draw the point as a 5x5 rectangle
+ // Don't draw if off the screen.
+ //----------------------------------------------
+
+ if (x > SCREEN_WIDTH || x < 0 || y > SCREEN_HEIGHT || y < 0)
+ {
+#ifdef DEBUG_PAGE_MAP
+ printf(" > %d..%d : OFF SCREEN", SCREEN_WIDTH, SCREEN_HEIGHT);
+#endif
+ }
+ else
+ {
+ gdk_draw_rectangle(MAP_PIX, gc, TRUE, x - rect/2, y - rect/2, rect, rect);
+#ifdef DEBUG_PAGE_MAP
+ printf(" rect @ [%f %f]", p->lon, p->lat);
+#endif
+ }
+
+ //----------------------------------------------
+ // Draw the route as a line.
+ // DO draw if out of bounds, but make it grey.
+ //----------------------------------------------
+
+ if (suppress)
+ {
+ gdk_draw_line(MAP_PIX, gc, lla_x0, lla_y0, x, y);
+#ifdef DEBUG_PAGE_MAP
+ // printf(" line (%d %d)-->(%d %d)", lla_x0, lla_y0, x, y);
+#endif
+ }
+#ifdef DEBUG_PAGE_MAP
+ printf("\n");
+#endif
+
+ lla_x0 = x;
+ lla_y0 = y;
+}
+
+//------------------------------------------------------------------------------------
+//
+// MAP_draw_all_points()
+//
+//------------------------------------------------------------------------------------
+
+static void
+MAP_draw_all_points()
+{
+ MeterScale& m = scales[scale_index];
+ MAP_draw_scale(m.scale, m.ruler_meters, m.ruler_dividers);
+
+ // printf("MAP_draw_all_points() %d %d\n", indexLLA, nLLA);
+
+ if (!nLLA) return;
+
+ lla_x0 = pixel_offset_x;
+ lla_y0 = pixel_offset_y;
+
+ MAP_draw_avg_circle(&avg_lla); // average circle
+
+ lla* p = lla_begin();
+ if (!p) return;
+
+ MAP_reset_position_accum();
+#ifdef DEBUG_PAGE_MAP
+ int i = 0;
+ printf("%d) ", i);
+#endif
+ MAP_draw_position(p, false); // first point is not suppressed.
+ do
+ {
+ p = lla_next();
+#ifdef DEBUG_PAGE_MAP
+ printf("%d) ", ++i);
+#endif
+ MAP_draw_position(p);
+ } while (!lla_last());
+
+#if 0 // DEBUG_PAGE_MAP
+ i = 0;
+ p = lla_begin();
+ do
+ {
+ printf("%d) 0x%x [%f %f]\n", i++, p, p->lon, p->lat);
+ p = lla_next();
+ } while (!lla_last());
+#endif
+}
+
+//-----------------------------------------------------------------------------------
+//
+// MAP_draw_scale()
+//
+// Draw the meter scale, text, sub-markers,
+// circle, and text on the circle.
+//
+//-----------------------------------------------------------------------------------
+
+static void
+MAP_draw_scale(double mult, int meters, int nDividers)
+{
+ GdkGC* gc = getGC(false);
+
+ double width = mult * static_cast<double> (meters);
+ int w = static_cast<int> (width);
+
+ //----------------------------------------------
+ // Draw the scale
+ //----------------------------------------------
+
+ int x0 = 10; // Arbitrary scale location choice...
+ int y0 = 20;
+
+ int x1 = x0 + w;
+ int y1 = y0;
+ gdk_draw_line(MAP_PIX, gc, x0, y0, x1, y1);
+ gdk_draw_line(MAP_PIX, gc, x0, y0, x0, y0 + 8);
+ gdk_draw_line(MAP_PIX, gc, x1, y1, x1, y1 + 8);
+
+ //----------------------------------------------
+ // Draw the sub-scale markers
+ //----------------------------------------------
+
+ int sub = w/nDividers;
+ for (x0 += sub; x0 < x1; x0 += sub)
+ {
+ gdk_draw_line(MAP_PIX, gc, x0, y0, x0, y0 + 4);
+ }
+
+ //----------------------------------------------
+ // Compute and format the scale text
+ //----------------------------------------------
+
+ char buf[10];
+ if (meters >= 1000) sprintf(buf, "%d km", meters/1000);
+ else sprintf(buf, "%d m", meters );
+
+ //----------------------------------------------
+ // Draw the scale text
+ //----------------------------------------------
+
+ pango_layout_set_text(MAP_text, buf, -1);
+ int h;
+ pango_layout_get_pixel_size(MAP_text, 0, &h);
+ gdk_draw_layout(MAP_PIX, gc, x1 + 3, y0 - h/2, MAP_text);
+
+ //-------------------------------------------------------------------------
+ // Draw the radius circle and text
+ //-------------------------------------------------------------------------
+
+ centerOfWindow(x0, y0);
+
+ int size = 2*w + 1;
+ // printf("MAP circle (%d %d)==>(%d %d) size %d\n", x0, y0, x0-w, y0-w, size);
+ gdk_draw_arc(MAP_PIX, gc, FALSE,
+ x0-w, y0-w, size, size, 0, 360 * DEGREE_64);
+ gdk_draw_layout(MAP_PIX, gc, x0 + w + 3, y0 - h/2, MAP_text);
+
+#if 0
+ //----------------------------------------------
+ // Draw 15x15 cross
+ //----------------------------------------------
+ gdk_draw_line(MAP_PIX, gc, x0-7, y0 , x0+7, y0 );
+ gdk_draw_line(MAP_PIX, gc, x0 , y0-7, x0 , y0+7);
+#else
+ //-------------------------------------------------------------------------
+ // Experiment with a NxN grey spot in the center.
+ //-------------------------------------------------------------------------
+ size = sub/2;
+ // printf("MAP spot (%d %d)==>(%d %d) size %d\n", x0, y0, x0-w, y0-w, size);
+ gdk_draw_arc(MAP_PIX, gc, TRUE,
+ x0-size-1, y0-size-1, sub, sub, 0, 360 * DEGREE_64);
+#endif
+
+}
+
+GtkLabel* map_scale_label = 0;
+
+
+static void meter_scale_reset()
+{
+ scale_index = 8;
+ pixels_per_meter = scales[scale_index].scale;
+}
+
+static double meter_scale()
+{
+ return scales[scale_index].scale;
+}
+
+//------------------------------------------------------------------------------------
+//
+// MAP_redraw()
+//
+//------------------------------------------------------------------------------------
+
+static void
+MAP_redraw()
+{
+ // printf("MAP_redraw\n");
+ if (!MAP_PIX) return;
+ page_MAP_alloc_colors();
+
+ MAP_clear();
+ gtk_button_set_label(button_style, TrackStyle::getLabel());
+
+ computePixelBaseline();
+ MAP_draw_all_points();
+ gtk_widget_queue_draw_area(GTK_WIDGET(MAP), 0, 0, 476, 476);
+ map_have_new_pos = false;
+
+ set_fix_label();
+}
+
+//------------------------------------------------------------------------------------
+//
+// page_MAP_done()
+//
+//------------------------------------------------------------------------------------
+
+void
+page_MAP_done()
+{
+ if (!map_have_new_pos) return;
+ MAP_redraw();
+}
+
+//------------------------------------------------------------------------------------
+//
+// cb_meter_scale_change()
+//
+// GTK+ callback when the user pressed [+] or [-].
+//
+//------------------------------------------------------------------------------------
+
+static void
+cb_meter_scale_change(GtkWidget* w, gpointer data)
+{
+ int x = GPOINTER_TO_INT(data);
+ int new_index = scale_index + x;
+ if (new_index < 0) new_index = 0;
+ if (new_index >= MAX_SCALES) new_index = MAX_SCALES - 1;
+ if (new_index == scale_index)
+ {
+ return; // nothing changed!
+ }
+ scale_index = new_index;
+
+ MeterScale& ms = scales[scale_index];
+ pixels_per_meter = ms.scale;
+
+ char buf[64];
+ sprintf(buf, "Scale %s", ms.name);
+ gtk_label_set_text(map_scale_label, buf);
+ MAP_recompute_xy_pixels("scale change");
+ MAP_redraw();
+}
+
+//------------------------------------------------------------------------------------
+//
+// MAP_recompute_xy_pixels()
+//
+// Since the multiplier changed, we need to recompute the
+// int x,y = (int) double mult*(double meters_x,double meters_y).
+//
+//------------------------------------------------------------------------------------
+
+static void
+MAP_recompute_xy_pixels(const char* msg)
+{
+ // Only compute pixel baseline if:
+ // ===> mult changes <===
+ // ... or if average changes (when centering the average),
+ // ... or if newer position (when centering the last position)
+ computePixelBaseline();
+
+ int i = 0;
+ lla* p = lla_begin();
+ if (p) p->compute_xy_pixels(msg);
+ do
+ {
+ p = lla_next();
+ p->compute_xy_pixels(msg);
+ } while (!lla_last());
+}
+
+//------------------------------------------------------------------------------------
+//
+// page_MAP_init()
+//
+//------------------------------------------------------------------------------------
+
+void
+page_MAP_init()
+{
+ meter_scale_reset();
+ memset(LLA, 0, sizeof(LLA));
+ nLLA = 0;
+ indexLLA = 0;
+ centerOfWindow(lla_x0, lla_y0);
+ sum_lon = 0.0;
+ sum_lat = 0.0;
+ lla::restart();
+}
+
+//------------------------------------------------------------------------------------
+//
+// page_MAP_create()
+//
+//------------------------------------------------------------------------------------
+
+GtkWidget*
+page_MAP_create(GtkWidget* window)
+{
+ GtkWidget* label;
+ GtkWidget* button;
+ GtkWidget* w;
+ GtkWidget* box;
+ GtkObject* adj;
+ GtkWidget* table;
+
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ table = gtk_table_new(14, 2, TRUE);
+
+ //--------------------------------------------------------------------------
+ // label
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Position Plot");
+ gtk_label_set_justify((GtkLabel*)label, GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 0, 1);
+ gtk_widget_show(label);
+ map_label = GTK_LABEL(label);
+
+ MAP_text = gtk_widget_create_pango_layout(label, "");
+
+ //--------------------------------------------------------------------------
+ // window for the position plot
+ //--------------------------------------------------------------------------
+ w = gtk_drawing_area_new();
+ MAP = GTK_DRAWING_AREA(w);
+ gtk_drawing_area_size(MAP, 500, 500);
+
+ gtk_signal_connect(GTK_OBJECT(w), "configure_event",
+ G_CALLBACK(configure_MAP_event), w);
+
+ gtk_signal_connect(GTK_OBJECT(w), "expose_event",
+ G_CALLBACK(expose_MAP_event), w);
+
+ gtk_widget_set_events(w, GDK_EXPOSURE_MASK);
+ gtk_table_attach_defaults(GTK_TABLE (table), w, 0, 2, 1, 12);
+ gtk_widget_show(w);
+
+ //--------------------------------------------------------------------------
+ // Meter scaling
+ //--------------------------------------------------------------------------
+
+ box = gtk_hbox_new(FALSE, 1);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 0);
+
+ label = gtk_label_new ("Scale x1");
+ gtk_widget_show (label);
+ map_scale_label = GTK_LABEL(label);
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label("+");
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (cb_meter_scale_change), (gpointer) -1);
+ gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label("-");
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (cb_meter_scale_change), (gpointer) +1);
+ gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);
+ gtk_widget_show(button);
+
+ gtk_widget_show (box);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 2, 12, 13);
+
+ //--------------------------------------------------------------------------
+ // Box to hold the center style button
+ // and the position slider.
+ //--------------------------------------------------------------------------
+
+ box = gtk_hbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 0);
+
+ //--------------------------------------------------------------------------
+ // Track style button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label(TrackStyle::getLabel());
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_track_style), button);
+ gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
+ gtk_widget_show(button);
+ button_style = GTK_BUTTON(button);
+
+ //--------------------------------------------------------------------------
+ // Position adjuster
+ //--------------------------------------------------------------------------
+ adj = gtk_adjustment_new(1.0, 1.0, 1.0, 1.0, 1.0, 1.0);
+ g_signal_connect (G_OBJECT (adj), "value_changed",
+ G_CALLBACK (cb_change_center), (gpointer) adj);
+ adj_center = GTK_ADJUSTMENT(adj);
+ scale_center = gtk_hscale_new(adj_center);
+ scale_init(GTK_SCALE(scale_center));
+ gtk_widget_set_sensitive(scale_center, false);
+ gtk_box_pack_start (GTK_BOX (box), scale_center, TRUE, TRUE, 1);
+ gtk_widget_show (scale_center);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 1, 13, 14);
+ gtk_widget_show (box);
+
+ //--------------------------------------------------------------------------
+ // km/h or mph
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("mph");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_mph), button);
+ gtk_table_attach_defaults(GTK_TABLE (table), button, 1, 2, 13, 14);
+ gtk_widget_show(button);
+
+ gtk_widget_show(table);
+
+ page_MAP_init();
+ return table;
+}
+
+static lla t;
+
+static void
+page_map_report_dist(FILE* f, const char* msg, lla* p, lla* avg)
+{
+ fprintf(f, "%s position %f %f", msg, p->lon, p->lat);
+
+ if (avg != p)
+ {
+ t = *p;
+ t.compute_xy_meters_abs(avg);
+ double d = sqrt(t.meters_x*t.meters_x + t.meters_y*t.meters_y);
+ if (d > 0.09) fprintf(f, " %.1f m from average", d);
+ }
+ fprintf(f, "\n");
+}
+
+void
+page_map_report(FILE* f)
+{
+ int n = fix_good;
+ if (n > MAX_LLA) n = MAX_LLA;
+ fprintf(f, "%d positions obtained, %d plotted\n", fix_good, n);
+
+ lla* p0 = lla_begin();
+ lla* pA = TrackStyle::getReference(TrackStyle::AVERAGE);
+ lla* pN = TrackStyle::getReference(TrackStyle::POINT_LAST);
+
+ page_map_report_dist(f, " First", p0, pA);
+ page_map_report_dist(f, "Average", pA, pA);
+ page_map_report_dist(f, " Last", pN, pA);
+}
Added: developers/olv/openmoko-agpsui2/src/page_speed.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_speed.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_speed.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,236 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+#include "agps.h"
+#include "sv_bar.h"
+
+// TODO:
+// 1) Connect the needle to real GPS activities
+// 2) Add numbers and tick marks to the dials.
+
+void notebook_expose(const char* pageName);
+
+static GtkDrawingArea* speed;
+static GdkPixmap* speed_PIX = 0;
+static PangoLayout* speed_text;
+
+static GdkGC* blue_gc = 0;
+static GdkGC* grey_gc = 0;
+
+extern GdkGC* alloc_color(GdkPixmap* pm, const char* color);
+
+static void
+speed_alloc_colors()
+{
+ if (!speed_PIX) return;
+ if (!blue_gc) blue_gc = alloc_color(speed_PIX, "Blue");
+ if (!grey_gc) grey_gc = alloc_color(speed_PIX, "SlateGrey");
+}
+
+static void
+speed_clear()
+{
+ if (!speed_PIX) return;
+ GtkWidget* w = GTK_WIDGET(speed);
+ gdk_draw_rectangle(speed_PIX, w->style->white_gc, TRUE,
+ 0, 0,
+ w->allocation.width,
+ w->allocation.height);
+}
+
+static gboolean
+configure_speed_event(GtkWidget* w, GdkEventConfigure* event)
+{
+ if (speed_PIX)
+ {
+ g_object_unref(speed_PIX);
+ }
+
+ //--------------------------------------------------------------------------
+ // pixmap
+ //--------------------------------------------------------------------------
+ speed_PIX = gdk_pixmap_new(w->window,
+ w->allocation.width,
+ w->allocation.height, -1);
+ speed_clear();
+ return TRUE;
+}
+
+static gboolean
+expose_speed_event(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("SP");
+ if (speed_PIX)
+ {
+ GdkRectangle& a = event->area;
+ gdk_draw_drawable(w->window,
+ w->style->fg_gc[GTK_WIDGET_STATE(w)],
+ speed_PIX, a.x, a.y, a.x, a.y, a.width, a.height);
+ }
+ return FALSE;
+}
+
+static GdkGC*
+getGC(bool used)
+{
+ speed_alloc_colors();
+ GdkGC* gc = grey_gc;
+ if (used) gc = blue_gc;
+ if (!gc) gc = GTK_WIDGET(speed)->style->black_gc;
+ return gc;
+}
+
+enum
+{
+ CENTER_XY = 3,
+ CENTER_X = 1,
+ CENTER_Y = 2,
+ CENTER_NONE = 0,
+
+ ALIGN_BOTTOM = 16,
+ ALIGN_RIGHT = 32
+};
+
+static void
+speed_draw_text(int x, int y, const char* t,
+ int center = CENTER_XY, GdkGC* gc = 0)
+{
+ if (!gc) gc = getGC(false);
+ pango_layout_set_text(speed_text, t, -1);
+ if (center)
+ {
+ int w;
+ int h;
+ pango_layout_get_pixel_size(speed_text, &w, &h);
+ if (center & CENTER_X ) x -= w/2;
+ else if (center & ALIGN_RIGHT ) x -= w;
+ if (center & CENTER_Y ) y -= h/2;
+ else if (center & ALIGN_BOTTOM) y -= h;
+ }
+ // printf("speed_draw_text(%d,%d,\"%s\", %d)\n", x, y, t, center);
+ gdk_draw_layout(speed_PIX, gc, x, y, speed_text);
+}
+
+static void
+speed_draw_line(int x0, int y0, int x1, int y1)
+{
+ // printf("speed_draw_line(%d,%d,%d,%d)\n", x0, y0, x1, y1);
+ GdkGC* gc = GTK_WIDGET(speed)->style->black_gc;
+ gdk_draw_line(speed_PIX, gc, x0, y0, x1, y1);
+}
+
+static void
+speed_draw_dial(const char* name, int x, int y)
+{
+ GdkGC* gc = getGC(true);
+
+ int radius = PIXMAP_WIDTH/4 - 3;
+ int width = radius * 2;
+ int height = width;
+ int arc0 = 0;
+ int arcN = 360 * DEGREE_64;
+ gdk_draw_arc(speed_PIX, gc, FALSE,
+ x+3, y+3,
+ width, height,
+ arc0, arcN);
+
+ int cx = x + PIXMAP_WIDTH/4;
+ int cy = y + PIXMAP_WIDTH/4;
+ speed_draw_text(cx, cy-radius/2, name);
+
+ speed_draw_line(cx,cy, cx,cy-radius);
+}
+
+static void
+speed_draw_dials()
+{
+ int h = PIXMAP_WIDTH/2;
+
+ speed_draw_dial("SPEED", 0, 0);
+ speed_draw_dial("ALT", h, 0);
+ speed_draw_dial("HEADING", 0, h);
+ speed_draw_dial("VERTICAL\nSPEED", h, h);
+
+ gtk_widget_queue_draw_area(GTK_WIDGET(speed), 0, 0,
+ PIXMAP_WIDTH, PIXMAP_WIDTH);
+}
+
+void
+page_speed_done()
+{
+ if (!speed_PIX) return;
+ speed_clear();
+ speed_draw_dials();
+}
+
+GtkWidget*
+page_speed_create(GtkWidget* window)
+{
+ GtkWidget* label;
+ GtkWidget* button;
+ GtkWidget* w;
+ GtkWidget* vbox;
+ GtkWidget* table;
+
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ table = gtk_table_new(14, 2, TRUE);
+
+ //--------------------------------------------------------------------------
+ // label
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Indicators");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 0, 1);
+ gtk_widget_show(label);
+
+ speed_text = gtk_widget_create_pango_layout(label, "");
+
+ //--------------------------------------------------------------------------
+ // window for the various dials
+ //--------------------------------------------------------------------------
+ w = gtk_drawing_area_new();
+ speed = GTK_DRAWING_AREA(w);
+ gtk_drawing_area_size(speed, PIXMAP_WIDTH, PIXMAP_WIDTH);
+
+ gtk_signal_connect(GTK_OBJECT(w), "configure_event",
+ G_CALLBACK(configure_speed_event), w);
+
+ gtk_signal_connect(GTK_OBJECT(w), "expose_event",
+ G_CALLBACK(expose_speed_event), w);
+
+ gtk_widget_set_events(w, GDK_EXPOSURE_MASK);
+ gtk_table_attach_defaults(GTK_TABLE (table), w, 0, 2, 1, 14);
+ gtk_widget_show(w);
+
+ gtk_widget_show(table);
+ return table;
+}
+
+void
+page_speed_report(FILE* f)
+{
+ fprintf(f, "Say something about %s/%d\n", __FILE__, __LINE__);
+}
Added: developers/olv/openmoko-agpsui2/src/page_stats.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_stats.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_stats.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,322 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "agps.h"
+#include "sv_bar.h"
+
+// TODO:
+// 1) Connect the stats items to real GPS activities
+
+void notebook_expose(const char* pageName);
+static void page_stats_fix_time_update(int x);
+enum
+{
+ MASK_TTF = 1,
+ MASK_TTFF = 2
+};
+
+static GtkLabel* wid_ttff;
+static GtkLabel* wid_ttf;
+
+class FixTime
+{
+public:
+ void init();
+ void fix_time(float t);
+ char* report(int n, char* buf) const;
+
+ FixTime(const char* name) : name_(name)
+ {
+ init();
+ };
+
+private:
+ int n_; // Number of samples
+
+ double min_;
+ double max_;
+
+ double mean_;
+ double S_;
+
+ const char* name_;
+};
+
+void
+FixTime::init()
+{
+ min_ = 99999.0;
+ max_ = 0.0;
+ n_ = 0;
+ mean_ = 0.0;
+ S_ = 0.0;
+}
+
+FixTime ttf ("TTF" ); // Time to fix
+FixTime ttff("TTFF"); // Time to first fix
+
+void
+FixTime::fix_time(float t)
+{
+ ++n_;
+
+ // printf("%s += %.1f %d\n", name_, t, n_);
+
+ double delta = t - mean_;
+ mean_ += delta / (double) n_;
+ S_ += delta * (t - mean_);
+
+ if (t < min_) min_ = t;
+ if (t > max_) max_ = t;
+}
+
+char*
+FixTime::report(int n, char* buf) const
+{
+ if (n_ < 1)
+ {
+ sprintf(buf, "%s(%d) Min: - s Max: - s\n"
+ "Average: - std - ",
+ name_, n_);
+ }
+ else
+ {
+ sprintf(buf, "%s(%d) Min: %.1f s Max: %.1f s\n"
+ "Average: %.1f s std %.1f",
+ name_, n_,
+ min_, max_, mean_, sqrt(S_/n_));
+ }
+ return buf;
+}
+
+void
+page_stats_fix_time(float TTF, float TTFF)
+{
+ if (TTFF > 0.0)
+ {
+ ttff.fix_time(TTFF);
+ page_stats_fix_time_update(MASK_TTFF);
+ }
+ else if (TTF > 0.0)
+ {
+ ttf.fix_time(TTF);
+ page_stats_fix_time_update(MASK_TTF);
+ }
+}
+
+void
+page_stats_init()
+{
+ ttf.init();
+ ttff.init();
+ page_stats_fix_time_update(MASK_TTFF | MASK_TTF);
+}
+
+static void
+page_stats_fix_time_report(FILE* f)
+{
+ char buf_ttf [128];
+ char buf_ttff[128];
+
+ fprintf(f, "Position Fix Time\n%s\n%s\n",
+ ttf.report (sizeof(buf_ttf ), buf_ttf ),
+ ttff.report(sizeof(buf_ttff), buf_ttff) );
+}
+
+void
+page_stats_report(FILE* f)
+{
+ // report the average position, CEP, etc.
+ page_stats_fix_time_report(f);
+}
+
+static void
+page_stats_fix_time_update(int x)
+{
+ char buf[128];
+
+ if (MASK_TTF & x)
+ {
+ ttf.report(sizeof(buf), buf);
+ gtk_label_set_text(wid_ttf, buf);
+ }
+
+ if (MASK_TTFF & x)
+ {
+ ttff.report(sizeof(buf), buf);
+ gtk_label_set_text(wid_ttff, buf);
+ }
+}
+
+void page_stats_done()
+{
+ // page_stats_position_update();
+ // page_stats_position_least_squares_update();
+ page_stats_fix_time_update(MASK_TTFF | MASK_TTF);
+}
+
+static gboolean
+expose_stats_event(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("ST");
+ return FALSE;
+}
+
+
+GtkWidget*
+page_stats_create(GtkWidget* window)
+{
+ GtkWidget* label;
+ GtkWidget* button;
+ GtkWidget* w;
+ GtkWidget* vbox;
+ GtkWidget* table;
+
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ table = gtk_table_new(14, 2, TRUE);
+ gtk_signal_connect(GTK_OBJECT(table), "expose_event",
+ G_CALLBACK(expose_stats_event), w);
+
+ //--------------------------------------------------------------------------
+ // Position Average
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Position Average");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 0, 1);
+ gtk_widget_show(label);
+
+ //----------------------------------------------------------------------
+ // Position Average : Lat..StdDev
+ //----------------------------------------------------------------------
+ label = gtk_label_new("Lat: 37.123456 N");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 1, 1, 2);
+ gtk_widget_show(label);
+ label = gtk_label_new("StdDev: 0.0 m ");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 1, 2, 1, 2);
+ gtk_widget_show(label);
+
+ //----------------------------------------------------------------------
+ // Position Average : Lon..StdDev
+ //----------------------------------------------------------------------
+ label = gtk_label_new("Lon: 121.654321 W");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 1, 2, 3);
+ gtk_widget_show(label);
+ label = gtk_label_new("StdDev: 0.0 m ");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 1, 2, 2, 3);
+ gtk_widget_show(label);
+
+ //----------------------------------------------------------------------
+ // Position Average : Alt..StdDev
+ //----------------------------------------------------------------------
+ label = gtk_label_new("Alt: 123 m");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 1, 3, 4);
+ gtk_widget_show(label);
+ label = gtk_label_new("StdDev: 0.0 m ");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 1, 2, 3, 4);
+ gtk_widget_show(label);
+
+ //--------------------------------------------------------------------------
+ // Least Squares Average
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Least Squares Average");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 4, 5);
+ gtk_widget_show(label);
+
+ //----------------------------------------------------------------------
+ // Least Squares Average : Lat..StdDev
+ //----------------------------------------------------------------------
+ label = gtk_label_new("Lat: 37.123456 N");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 1, 5, 6);
+ gtk_widget_show(label);
+ label = gtk_label_new("StdDev: 0.0 m ");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 1, 2, 5, 6);
+ gtk_widget_show(label);
+
+ //----------------------------------------------------------------------
+ // Least Squares Average : Lon..StdDev
+ //----------------------------------------------------------------------
+ label = gtk_label_new("Lon: 121.654321 W");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 1, 6, 7);
+ gtk_widget_show(label);
+ label = gtk_label_new("StdDev: 0.0 m ");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 1, 2, 6, 7);
+ gtk_widget_show(label);
+
+ //----------------------------------------------------------------------
+ // Least Squares Average : Alt..StdDev
+ //----------------------------------------------------------------------
+ label = gtk_label_new("Alt: 123 m");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 1, 7, 8);
+ gtk_widget_show(label);
+ label = gtk_label_new("StdDev: 0.0 m ");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 1, 2, 7, 8);
+ gtk_widget_show(label);
+
+ //--------------------------------------------------------------------------
+ // Position Fix Time
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Position Fix Time");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 9, 10);
+ gtk_widget_show(label);
+
+ //----------------------------------------------------------------------
+ // Position Fix Time : TTF
+ //----------------------------------------------------------------------
+ label = gtk_label_new("");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 10, 12);
+ gtk_widget_show(label);
+ wid_ttf = GTK_LABEL(label);
+
+ //----------------------------------------------------------------------
+ // Position Fix Time : TTFF
+ //----------------------------------------------------------------------
+ label = gtk_label_new("");
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE (table), label, 0, 2, 12, 14);
+ gtk_widget_show(label);
+ wid_ttff = GTK_LABEL(label);
+
+ page_stats_init();
+
+ gtk_widget_show(table);
+ return table;
+}
Added: developers/olv/openmoko-agpsui2/src/page_stress.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_stress.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_stress.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,329 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PAGE_STRESS_H__ // {
+#include "page_stress.h"
+#endif // }
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef PAGE_STRESS
+
+extern void create_range_controls(GtkWidget* window, GtkWidget* vbox, bool test);
+extern const char* gllin_detect(void);
+extern const char* gllin_start(void);
+extern const char* gllin_stop(void);
+extern void stress_cb_start(GtkWidget* label);
+extern void clearStats();
+extern void notebook_expose(const char* pageName);
+extern bool doing_reset_gps;
+
+extern void page_pm_batch_next();
+extern void page_pm_fix_done();
+extern void page_pm_batch_done();
+
+GtkLabel* stressLabel;
+extern void NMEA_MSG(const char* msg);
+
+static gboolean
+expose_stress_event(GtkWidget* w, GdkEventExpose* event)
+{
+ notebook_expose("RR");
+ return FALSE;
+}
+
+static bool stress_test = false;
+extern void page_main_gllin(bool start);
+
+bool
+page_stress_on(void)
+{
+ return stress_test;
+}
+
+void
+page_stress_msg(const char* msg)
+{
+ gtk_label_set_text(stressLabel, msg);
+}
+
+void page_stress_done(void)
+{
+}
+
+static void
+on_clicked_reset_gps(GtkWidget* w, gpointer d)
+{
+ page_stress_msg("Resetting GPS ...");
+ gllin_stop();
+ doing_reset_gps = true;
+ gllin_start();
+ doing_reset_gps = false;
+ sleep(1);
+ gllin_stop();
+ page_stress_msg("GPS device reset is completed.");
+ page_pm_batch_done();
+}
+
+void
+page_stress_msg_int(const char* msg, int n)
+{
+ char buf[88];
+ sprintf(buf, "%s %d", msg, n);
+ page_stress_msg(msg);
+}
+
+int
+stress_rand(int min, int max)
+{
+ int result = min + rand() % (max-min);
+ printf("stress_rand(%d,%d) %d\n", min, max, result);
+ return result;
+}
+
+guint stress_timeout_id = 0;
+static guint on_timeout_stress(GtkWidget* w, gpointer d);
+
+// Caution: called from a timer thread, so all called GTK+ widgets
+// must be protected by gdk_threads_enter() and gdk_threads_leave()
+
+static void
+stress_stop()
+{
+ stress_timeout_id = 0;
+ // gdk_threads_remove_timeout(stress_timeout_id);
+
+ gllin_stop();
+ page_stress_msg("Stopping");
+}
+
+//------------------------------------------------------------------------------------
+//
+// Report
+//
+// page_stress_do_report() - generate a report
+// page_stress_set_report_name() - update the report label on the button.
+// on_clicked_report() - start the generation of a report.
+//
+//------------------------------------------------------------------------------------
+
+void notebook_report(FILE* f);
+
+static int report_id = 0;
+extern const char* page_main_test_name(void);
+
+bool
+page_stress_do_report(void)
+{
+ const char* test_name = page_main_test_name();
+ if (!test_name) return false;
+
+ char report_name[32];
+ sprintf(report_name, "./log/%s-R-%d.txt", test_name, report_id);
+
+ FILE* f = fopen(report_name, "a+");
+ if (!f)
+ {
+ fprintf(stderr, "omgui: can't create report file %s: %d %s\n",
+ report_name, errno, strerror(errno));
+ return false;
+ }
+ notebook_report(f);
+ fclose(f);
+ ++report_id;
+ return true;
+}
+
+static GtkButton* wid_report = 0;
+
+void
+page_stress_set_report_name(void)
+{
+ if (wid_report)
+ {
+ char report_name[32];
+ sprintf(report_name, "Report %s-R-%d", page_main_test_name(), report_id);
+ gtk_button_set_label(wid_report, report_name);
+ }
+}
+
+static void
+on_clicked_report(GtkWidget* w, gpointer d)
+{
+ if (page_main_test_name())
+ {
+ page_stress_do_report();
+ page_stress_set_report_name();
+ }
+}
+
+// Caution: MIGHT be called from a timer thread, so all called GTK+ widgets
+// must be protected by gdk_threads_enter() and gdk_threads_leave()
+
+#ifdef OPT_STRESS_FEATURE // {
+
+static void
+stress_start(void)
+{
+ page_main_gllin(true);
+ int timeout = stress_rand(2,600); // run time is 2..600 seconds.
+ stress_timeout_id = g_timeout_add_seconds(timeout, (gboolean (*)(void*))on_timeout_stress, 0);
+ page_stress_msg_int("Started stress test", timeout);
+}
+
+static guint
+on_timeout_stress(GtkWidget* w, gpointer d)
+{
+ if (!stress_timeout_id) return FALSE;
+ stress_stop();
+
+ int timeout = stress_rand(0,30); // Sleep between 0 and 30 seconds;
+ page_stress_msg_int("Stress delay", timeout);
+ sleep(timeout);
+
+ stress_start();
+ return FALSE;
+}
+
+static void
+on_clicked_stress(GtkWidget* w, gpointer d)
+{
+ stress_test = !stress_test;
+ if (stress_test)
+ {
+ stress_start();
+ }
+ else
+ {
+ stress_stop();
+ }
+}
+#endif
+
+void
+page_stress_RID()
+{
+ page_pm_batch_next();
+}
+
+void
+page_stress_FIX()
+{
+ page_pm_fix_done();
+}
+
+void
+page_stress_EXIT()
+{
+ // page_main_gllin(false); // don't have this yet.
+ page_pm_batch_done();
+ gllin_stop();
+}
+
+GtkWidget*
+page_stress_create(GtkWidget* window)
+{
+ GtkWidget* label;
+ GtkWidget* button;
+ GtkWidget* vbox;
+ GtkWidget* table;
+
+ //--------------------------------------------------------------------------
+ // table
+ //--------------------------------------------------------------------------
+ table = gtk_table_new(14, 2, TRUE);
+ gtk_signal_connect(GTK_OBJECT(table), "expose_event",
+ G_CALLBACK(expose_stress_event), table);
+
+ //--------------------------------------------------------------------------
+ // label
+ //
+ // All text from the "stress" page goes to this stressLabel
+ //--------------------------------------------------------------------------
+ label = gtk_label_new("Future panel to show stress test results");
+ stressLabel = GTK_LABEL(label);
+ gtk_label_set_justify(stressLabel, GTK_JUSTIFY_LEFT);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 1, 8);
+ gtk_widget_show(label);
+
+#ifdef OPT_STRESS_FEATURE
+ //--------------------------------------------------------------------------
+ // start stress test button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("Start Stress Test");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_stress), label);
+ gtk_table_attach_defaults(GTK_TABLE (table), button, 0, 2, 8, 9);
+ gtk_widget_show(button);
+#endif
+
+ //--------------------------------------------------------------------------
+ // range controls
+ //--------------------------------------------------------------------------
+ create_range_controls(window, table, true);
+
+ //--------------------------------------------------------------------------
+ // reset GPS button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("Reset GPS");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_reset_gps), label);
+ gtk_table_attach_defaults(GTK_TABLE (table), button, 0, 1, 13, 14);
+ gtk_widget_show(button);
+
+ //--------------------------------------------------------------------------
+ // report button
+ //--------------------------------------------------------------------------
+ button = gtk_button_new_with_label("Report");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(on_clicked_report), NULL);
+ gtk_table_attach_defaults(GTK_TABLE (table), button, 1, 2, 13, 14);
+ gtk_widget_show(button);
+ wid_report = GTK_BUTTON(button);
+
+ gtk_widget_show(table);
+ return table;
+}
+
+#else // } {
+
+void page_stress_msg(const char* msg)
+{
+}
+
+void page_stress_done(void)
+{
+}
+
+#endif // }
+
+
+extern void pm_report(FILE* f, bool stress);
+
+void
+page_stress_report(FILE* f)
+{
+ pm_report(f, true);
+}
Added: developers/olv/openmoko-agpsui2/src/page_stress.h
===================================================================
--- developers/olv/openmoko-agpsui2/src/page_stress.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/page_stress.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PAGE_STRESS_H__ // {
+#define PAGE_STRESS_H__
+
+#ifndef PAGE_STRESS_H__ // {
+#include "page_stress.h"
+#endif // }
+
+#ifndef __GLIB_H__ // {
+#include <glib.h>
+#endif // }
+
+#define PAGE_STRESS
+// #undef PAGE_STRESS
+
+// Unfortunately, the stress test requires
+// the g_timeout_add_seconds() api which is
+// present in GTK+ v2.14 and later only....
+
+#if ( ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION >= 14)) \
+ || (GLIB_MAJOR_VERSION > 2) )
+#else
+#undef OPT_STRESS_FEATURE
+#endif
+
+#endif // }
Added: developers/olv/openmoko-agpsui2/src/pm_agps.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/pm_agps.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/pm_agps.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,724 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include "nmea.h"
+
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+
+int gllin_fd();
+extern void page_MAP_have_lla(double lon, double lat, int alt, int heading, int speed, int time);
+extern FILE *dump_nmea_fp;
+extern int debug_all;
+
+void page_log_append(const char *nmea);
+
+#define FIFO "/tmp/nmeaNP"
+#define NV1 "./NVRAM1.DAT"
+#define NV2 "./NVRAM2.DAT"
+#define LLL "log"
+
+#undef SLOG
+
+#ifdef SLOG
+#define LOG "/dev/log"
+#endif
+
+#define SIZE 128
+#define GOT 3
+
+FILE* fp1 = NULL;
+int finish = 0;
+char* gllin_stop(void);
+gint agps_cb_nmea_tag = 0;
+static void agps_nmea_process(GtkWidget* label, unsigned char* buf, int size);
+unsigned long int runtime();
+extern void page_SS_init();
+extern void page_RFI_handle_GSV(nmea_gsv* pGSV);
+extern void page_RFI_handle_GGA(nmea_gga* pGGA);
+extern void pm_controls_nmea_epoch_done(void);
+extern void page_stress_RID();
+extern void page_stress_FIX();
+extern void page_stress_EXIT();
+
+//static char buffer_zone[1024]; // Somebody is overwriting a buffer.
+static struct nmea_gga n_gga;
+static struct nmea_rmc n_rmc;
+static struct nmea_gsv n_gsv[GOT];
+static struct nmea_gsa n_gsa;
+static struct nmea_lor n_lor;
+
+GtkLabel* agpsLabel = 0;
+
+void NMEA_MSG(const char* msg)
+{
+ if (agpsLabel)
+ {
+ gtk_label_set_text(agpsLabel, msg);
+ }
+}
+
+static void NMEA_DEBUG(const char* msg)
+{
+#if 0
+#ifdef DEBUG_LV1
+ printf("%s\n", msg);
+#endif
+#ifdef DEBUG_LV3
+ NMEA_MSG(msg);
+#endif
+#ifdef DEBUG_LV5
+ print(msg);
+#endif
+#ifdef SLOG
+ if (fp1) fputs(msg, fp1);
+#endif
+#endif
+}
+
+gboolean stop(GtkWidget *widget)
+{
+ finish = 1;
+ return FALSE;
+}
+
+void
+agps_fd(gpointer data, gint source, GdkInputCondition cond)
+{
+ // For stress test only:
+ // Only needed if the g_timeout_cb() is not thread-safe:
+ //
+ // page_main_poll_for_stop();
+ //
+
+ GtkWidget* label = GTK_WIDGET(data);
+ if (source != gllin_fd())
+ {
+ NMEA_DEBUG("fd mismatch");
+ return;
+ }
+ if (GDK_INPUT_READ != cond)
+ {
+ NMEA_DEBUG("gtk read callback condition mismatch");
+ return;
+ }
+ unsigned char buf[SIZE+1];
+ int n = read(source, buf, SIZE);
+ if (n > 0)
+ agps_nmea_process(label, buf, n);
+ else
+ printf("read failed\n");
+}
+
+void
+agps_cb_start(GtkWidget* label)
+{
+ agps_cb_nmea_tag = gdk_input_add(gllin_fd(), GDK_INPUT_READ, agps_fd, label);
+}
+
+void
+agps_cb_stop()
+{
+ gdk_input_remove(agps_cb_nmea_tag);
+}
+
+int fix_good = 0;
+int fix_fail = 0;
+int fix_total = 0;
+static int ttff;
+
+extern void page_MAP_init(void);
+
+void
+clearStats()
+{
+ fix_good = 0;
+ fix_fail = 0;
+ fix_total = 0;
+ ttff = 0;
+ page_SS_init();
+ page_MAP_init();
+}
+
+static char line_buffer[1024] = { 0 };
+static void agps_nmea_process_(GtkWidget* label, char* buf);
+
+//-------------------------------------------------------------------------------------
+//
+// agps_nmea_process()
+//
+// Convert the chunks of NMEA data into separate sentences.
+// Then process.
+//
+//-------------------------------------------------------------------------------------
+
+static unsigned int next_msg(GByteArray **pq)
+{
+ unsigned char *head, *tail, *end;
+ GByteArray *q = *pq;
+
+ if (q->len < 5)
+ return FALSE;
+
+ end = q->data + q->len;
+
+ head = q->data;
+ tail = end + 1;
+
+ while (head < end)
+ {
+ if (*head == 0xb5)
+ {
+ if (head + 6 > end)
+ break;
+
+ if (head[1] == 0x62)
+ {
+ int len;
+
+ len = head[4] | (head[5] << 8);
+ /* limit payload size */
+ if (len < 0x100)
+ {
+ tail = head + 6 + len + 2;
+
+ //printf("ubx of len %d, got %d\n", len, q->len);
+
+ break;
+ }
+ }
+ }
+ else if (*head == '$')
+ {
+ unsigned char *tmp = head + 1;
+
+ while (g_ascii_isprint(*tmp) && tmp < end)
+ tmp++;
+
+ if (tmp + 2 > end)
+ break;
+
+ if ((tmp[0] == '\r' || tmp[0] == '\n') && tmp[1] == '\n')
+ {
+ tail = tmp + 2;
+
+ break;
+ }
+ else
+ {
+ printf("nmea ends with 0x%02x 0x%02x\n", tmp[0], tmp[1]);
+ head = tmp - 1;
+ }
+ }
+
+ head++;
+ }
+
+ if (q->data < head)
+ {
+
+#if 0
+ if (head - q->data == 20 && q->data[0] == 0x10 && q->data[1] == 0x00)
+ {
+ unsigned char nav_status[] = { 0xb5, 0x62, 0x01, 0x03 };
+
+ q = g_byte_array_prepend(q, nav_status, sizeof(nav_status));
+
+ head = q->data;
+ tail = q->data + 24;
+ end = q->data + q->len;
+ }
+ else
+#endif
+ {
+ if (debug_all)
+ {
+ int i;
+
+ printf("abandoning %d bytes of %d bytes\n---\n", head - q->data, q->len);
+
+ for (i = 0; i < head - q->data; i++)
+ {
+ printf("0x%02x", q->data[i]);
+ printf("%c", (i % 16 == 15) ? '\n' : ' ');
+ }
+ printf("\n---\n");
+ }
+
+ q = g_byte_array_remove_range(q, 0, head - q->data);
+ }
+
+ *pq = q;
+ }
+
+ return (tail <= end) ? (tail - head) : 0;
+}
+
+#define READ32(p) (READ16(p) | READ16((p) + 2) << 16)
+#define READ16(p) ((p)[0] | (p)[1] << 8)
+#define READ8(p) ((p)[0])
+
+static void ubx_process(unsigned char *buf, size_t size)
+{
+ unsigned char *p, cls, id, checksum[2];
+ unsigned int i, payload;
+
+ if (size < 6 || buf[0] != 0xb5 || buf[1] != 0x62)
+ {
+ printf("invalid ubx\n");
+
+ return;
+ }
+
+ cls = buf[2];
+ id = buf[3];
+
+ payload = READ16(buf + 4);
+ if (6 + payload + 2 != size)
+ {
+ printf("wrong ubx size\n");
+
+ return;
+ }
+
+ checksum[0] = checksum[1] = 0;
+ for (i = 2; i < size - 2; i++)
+ {
+ checksum[0] += buf[i];
+ checksum[1] += checksum[0];
+ }
+
+ if (buf[size - 2] != checksum[0] || buf[size - 1] != checksum[1])
+ {
+ printf("wrong checksum (should be 0x%02x%02x, not 0x%02x%02x)\n",
+ checksum[0], checksum[1],
+ buf[size - 2], buf[size - 1]);
+
+ return;
+ }
+
+ p = &buf[6];
+
+ printf("received (0x%02x 0x%02x)\n", cls, id);
+
+ switch (cls)
+ {
+ case 0x05:
+ if (id == 0x01)
+ printf("(0x%02x 0x%02x) acked\n", p[0], p[1]);
+ break;
+ case 0x01:
+ switch (id)
+ {
+ case 0x03:
+ printf("STATUS %u 0x%x 0x%x 0x%x %u %u\n",
+ READ32(p) / 1000, READ8(p + 4), READ8(p + 5),
+ READ8(p + 6), READ32(p + 8), READ32(p + 12));
+ break;
+ case 0x22:
+ printf("TIME %u %d %d %u %u\n",
+ READ32(p) / 1000, READ32(p + 4), READ32(p + 8),
+ READ32(p + 12), READ32(p + 16));
+ break;
+ }
+ break;
+ }
+}
+
+static void
+agps_nmea_process(GtkWidget* label, unsigned char* buf, int size)
+{
+ static GByteArray *q;
+ int s;
+
+ if (!q)
+ {
+ q = g_byte_array_new();
+ if (!q)
+ return;
+ }
+
+ q = g_byte_array_append(q, buf, size);
+
+ while ((s = next_msg(&q)))
+ {
+ if (q->data[0] == '$')
+ {
+ memcpy(line_buffer, q->data, s - 2);
+ line_buffer[s - 2] = '\0';
+
+ agps_nmea_process_(label, line_buffer);
+ }
+ else
+ ubx_process(q->data, s);
+
+ q = g_byte_array_remove_range(q, 0, s);
+ }
+}
+
+//------------------------------------------------------------------------------
+//
+// nmea_to_ll(const char* s, float& lat)
+//
+// Convert 12345.678 into
+// 123 degrees, 45.678 minutes, or
+// 123.761300 degrees.
+//
+//------------------------------------------------------------------------------
+
+static float
+nmea_to_ll(const char* s)
+{
+ bool negate = false;
+ if (*s == '-')
+ {
+ negate = true;
+ ++s;
+ }
+
+ float fll;
+ sscanf(s, "%f", &fll); // 12345.678
+
+ int ill;
+ sscanf(s, "%d", &ill); // 12345
+ float degrees = ill / 100; // 123.0
+
+ fll -= degrees * 100; // 12345.678 - 12300.0 = 45.678
+ degrees += fll/60.0; // 123.0 + 45.678/60.0 = 123.7613
+ if (negate)
+ {
+ degrees = -degrees;
+ }
+ return degrees;
+}
+
+extern char testStartTime[];
+
+static char nmea_epoch_string[2048] = {0};
+
+const char*
+nmea_epoch()
+{
+ return nmea_epoch_string;
+}
+
+static void
+nmea_epoch_end(struct nmea_gga* gga, struct nmea_lor* lor)
+{
+ char tmp[1024];
+ char* p = tmp;
+ memset(tmp, 0, sizeof(tmp));
+
+ //p += sprintf(p, "Start time: %s\n", testStartTime);
+
+ // TODO: Report more info
+ // Be smarter about calling this procedure
+ // Save the data so we can press a "report" button to save to file.
+ {
+ unsigned long total_sec = runtime();
+ p += sprintf(p, "Module Uptime:");
+
+ if (total_sec > 59)
+ {
+ int hours = total_sec / 3600;
+ int min = (total_sec % 3600) / 60;
+ int sec = (total_sec % 60);
+
+ p += sprintf(p, " %02d:%02d:%02d", hours, min, sec);
+
+ }
+ p += sprintf(p, " (%d s)\n", (int) total_sec);
+ }
+
+ if (fix_total)
+ {
+ p += sprintf(p, "Fixes: %d good %d fail %d total\n",
+ fix_good, fix_fail, fix_total);
+ }
+ else
+ {
+ p += sprintf(p, "Starting\n");
+ }
+
+ if (ttff)
+ {
+ p += sprintf(p, "TTFF: %ds\n", ttff);
+ }
+ else
+ {
+ p += sprintf(p, "TTFF: -\n");
+ }
+
+ if (gga->time[0])
+ {
+ char fixTime[32];
+
+ fixTime[0] = gga->time[0];
+ fixTime[1] = gga->time[1];
+ fixTime[2] = ':';
+ fixTime[3] = gga->time[2];
+ fixTime[4] = gga->time[3];
+ fixTime[5] = ':';
+ fixTime[6] = gga->time[4];
+ fixTime[7] = gga->time[5];
+ fixTime[8] = gga->time[6];
+ fixTime[9] = gga->time[7];
+ fixTime[10] = gga->time[8];
+ fixTime[11] = 0;
+ p += sprintf(p, "UTC: %s\n", fixTime);
+ }
+ else
+ {
+ p += sprintf(p, "Fix time: -\n");
+ }
+
+ if (strlen(gga->latitude) && strlen(gga->longitude))
+ {
+ float lat = nmea_to_ll(gga->latitude);
+ float lon = nmea_to_ll(gga->longitude);
+
+ int alt;
+ sscanf(gga->alme, "%d", &alt);
+
+ const char* alt_units = "m";
+
+ p += sprintf(p,
+ "Latitude: %10.6f %s\n"
+ "Longitude: %10.6f %s\n"
+ "Altitude: %d %s\n"
+ "HDOP: %s\n",
+ lat, gga->la,
+ lon, gga->lo,
+ alt, alt_units,
+ gga->hdop);
+
+ if (strchr(gga->la, 'S'))
+ {
+ lat = -lat;
+ }
+
+ if (strchr(gga->lo, 'W'))
+ {
+ lon = -lon;
+ }
+
+ // TODO: fill in alt, speed, and heading
+
+ page_MAP_have_lla(lon, lat, 50, 0, 0, 123000);
+ }
+ else
+ {
+ p += sprintf(p,
+ "Latitude: -\n"
+ "Longitude: -\n"
+ "Altitude: -\n"
+ "HDOP: -\n");
+ }
+
+ if (gga->nos[0])
+ {
+ int nsat;
+ sscanf(gga->nos, "%d", &nsat);
+ p += sprintf(p, "Num sats: %d\n", nsat);
+ }
+ else
+ {
+ p += sprintf(p, "\n");
+ }
+
+ if (lor->rid[0])
+ {
+ p += sprintf(p, "Version: %s\n", lor->rid);
+ }
+ if (lor->nIgr)
+ {
+ p += sprintf(p, "IGR: %d) %s", lor->nIgr, lor->igr);
+ }
+ // g_printf("%s", tmp);
+ NMEA_MSG(tmp);
+
+ strcpy(nmea_epoch_string, tmp);
+
+ pm_controls_nmea_epoch_done();
+}
+
+//-------------------------------------------------------------------------------------
+//
+// agps_nmea_process_()
+//
+// Process the NMEA sentences.
+//
+//-------------------------------------------------------------------------------------
+
+static void
+agps_nmea_process_(GtkWidget* label, char* buf)
+{
+ int j = 0;
+
+ struct nmea_gga* gga = &n_gga;
+ struct nmea_rmc* rmc = &n_rmc;
+ struct nmea_gsv* gsv = n_gsv;
+ struct nmea_gsa* gsa = &n_gsa;
+ struct nmea_lor* lor = &n_lor;
+
+ NMEA_DEBUG(buf);
+
+ page_log_append(buf);
+ if (dump_nmea_fp)
+ g_fprintf(dump_nmea_fp, ">%s\n", buf);
+
+ if (strstr(buf,GGA))
+ {
+ memset(gga, 0, sizeof(struct nmea_gga));
+ NMEA_DEBUG("$GPGGA");
+ GPGGA(buf, gga);
+ //page_RFI_handle_GGA(gga);
+
+#ifdef DEBUG_LV2
+ printf("Sentence: %s\n", gga->sentence);
+ printf("FIX Taken: %s\n", gga->time);
+ printf("Latitude: %s\n", gga->latitude);
+ printf("%s\n", gga->la);
+ printf("Longitude: %s\n", gga->longitude);
+ printf("%s\n", gga->lo);
+ printf("Fix quality: %s\n", gga->fix_quality);
+ printf("Num of sat: %s\n", gga->nos);
+ printf("Horizontal dilution: %s\n", gga->hdop);
+ printf("Altitude: %s\n", gga->alme);
+ printf("%s\n", gga->al);
+ printf("Height of geoid: %s\n", gga->hog);
+ printf("%s\n", gga->ho);
+ printf("time in seconds: %s\n", gga->tis);
+ printf("DGPS ID: %s\n", gga->DGPS);
+ printf("checksum: %s\n", gga->checksum);
+#endif
+ }
+ else if (strstr(buf,RMC))
+ {
+ memset(rmc, 0, sizeof(struct nmea_rmc));
+ NMEA_DEBUG("$GPRMC");
+ if (strstr(buf, ",A,"))
+ {
+ ++fix_good;
+ if (fix_good > 2 && !ttff)
+ ttff = runtime();
+ }
+ else
+ {
+ ++fix_fail;
+ }
+ ++fix_total;
+
+ GPRMC(buf, rmc);
+ // g_printf("RMC: (%d+%d)/%d\n", fix_good, fix_fail, fix_total);
+ }
+ else if (strstr(buf,GSA))
+ {
+ memset(gsa, 0, sizeof(struct nmea_gsa));
+ NMEA_DEBUG("$GPGSA");
+ GPGSA(buf, gsa);
+#ifdef DEBUG_LV2
+ printf("Sentence: %s\n", gsa->sentence);
+ printf("Auto/Manual: %s\n", gsa->AM);
+ printf("mode: %s\n", gsa->mode);
+
+ for (i = 0; i < 12; ++i)
+ {
+ printf("PRN(%d): %s\n", i, gsa->id[i]);
+ }
+
+ printf("PDOP: %s\n", gsa->PDOP);
+ printf("HDOP: %s\n", gsa->HDOP);
+ printf("VDOP: %s\n", gsa->VDOP);
+ printf("checksum: %s\n", gsa->checksum);
+ printf("Num of Sate: %d\n",gsa->n);
+#endif
+ nmea_epoch_end(gga, lor);
+ }
+ else if (strstr(buf,GSV))
+ {
+ nmea_gsv* pGSV = gsv+j;
+ memset(pGSV, 0, sizeof(struct nmea_gsv));
+ NMEA_DEBUG("$GPGSV");
+ GPGSV(buf, pGSV);
+#ifdef DEBUG_LV6
+ printf("Sentence: %s\n", pGSV->sentence);
+ printf("Num of sentence: %s\n", pGSV->nose);
+ printf("sentence #: %s\n", pGSV->sn);
+ printf("Num of sate: %s\n", pGSV->nosa);
+
+ for (i = 0; i < pGSV->n; ++i)
+ {
+ printf("(%d) PRN: %s\n", i, pGSV->sate[i][0]); printf("(%d) Elevation: %s\n", i, pGSV->sate[i][1]);
+ printf("(%d) Azimuth: %s\n", i, pGSV->sate[i][2]);
+ printf("(%d) SNR: %s\n", i, pGSV->sate[i][3]);
+ }
+
+ printf("checksum: %s\n", (gsv+j)->checksum);
+#endif
+
+ //page_RFI_handle_GSV(pGSV);
+ ++j;
+ }
+ else if (strstr(buf,"PGLOR,RID"))
+ {
+ memset(lor, 0, sizeof(struct nmea_lor));
+ PGLOR_RID(buf, lor);
+ page_stress_RID();
+ }
+ else if (strstr(buf,"PGLOR,IG"))
+ {
+ PGLOR_IGR(buf, lor);
+ }
+ else if (strstr(buf,"PGLOR,FIX"))
+ {
+ PGLOR_FIX(buf, lor);
+ // nmea_epoch_end(gga, lor);
+ page_stress_FIX();
+ }
+ else if (strstr(buf,"PGLOR,EXIT"))
+ {
+ PGLOR_EXIT(buf, lor);
+ // nmea_epoch_end(gga, lor);
+ page_stress_EXIT();
+ }
+}
+
+void agps_stop(void)
+{
+ finish = TRUE;
+}
+
+
+#if 0
+
+
+
+#endif
Added: developers/olv/openmoko-agpsui2/src/pm_controls.cpp
===================================================================
--- developers/olv/openmoko-agpsui2/src/pm_controls.cpp 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/pm_controls.cpp 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,777 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+const char* start_type = "hot";
+bool allow_lto = true;
+extern bool doing_ptf;
+
+bool doing_stress = false;
+int stress_count = -1;
+
+static bool set_timeout = false;
+static bool set_accuracy_mask = false;
+static int accuracy_mask = 50;
+static int timeout = 64;
+static GtkWidget* wid_box_accuracy_mask;
+static GtkWidget* wid_box_timeout;
+static GtkAdjustment* wid_batch_adj;
+static GtkAdjustment* wid_fix_adj;
+
+//------------------------------------------------------------------------------
+//
+// Range/Scale Widgets for OMGUI
+//
+// Ken Yale
+// Global Locate
+//
+// Ranges:
+// Fix Period 0...64, where 0 is native.
+// Fix Type: HOT (default), WARM, COLD, SNR
+// Fix type has option for LTO on or off.
+// Batch count 1..1000 [only if the "do batches" is active]
+// Fix count 1..1000 [only if the "do batches" is active]
+//
+// Special Cases:
+// If Batch count is 0, then do a OMGUI stress test (forever).
+// Start the GLLIN, then wait fix_count fixes (good or bad), then
+// stop the GLLIN, sleep 1 second & repeat forever.
+// In this case, if fix_count is 0, then the fix_count is computed
+// to be a random number between 10 and 265 (inclusive).
+//
+// Buttons:
+// Do batches or not.
+// simulator used or not.
+// sensitivity/driving
+// logging on/off
+//
+// Behavior:
+// fix period adjustment is shared between RUN and TEST pages.
+// Simulator button is shared between RUN and TEST pages.
+//
+// All controls are disabled (but visible) when the GLLIN is running.
+//
+// All BATCH_COUNT and FIX_COUNT are invisble until BATCH is on.
+//
+//------------------------------------------------------------------------------
+
+static void cb_pos_menu_select( GtkWidget *item,
+ GtkPositionType pos )
+{
+ allow_lto = true;
+ start_type = (const char*) pos;
+
+ if (strstr(start_type, "(no LTO)"))
+ {
+ static char tmp_start[32];
+ strcpy(tmp_start, start_type);
+
+ char* p = strchr(tmp_start, '(');
+ p[-1] = 0;
+
+ allow_lto = false;
+ start_type = tmp_start;
+ }
+
+ printf("start type %s \"%s\"\n", start_type, (char*) pos);
+}
+
+int fix_rate = 0;
+
+GtkAdjustment* wid_fix_rate0 = 0;
+GtkAdjustment* wid_fix_rate1 = 0;
+
+static void cb_fix_rate(GtkAdjustment* adj)
+{
+ static bool locked = false;
+
+ if (!locked)
+ {
+ locked = true;
+ if (adj != wid_fix_rate0) gtk_adjustment_set_value(wid_fix_rate0, adj->value);
+ if (adj != wid_fix_rate1) gtk_adjustment_set_value(wid_fix_rate1, adj->value);
+ locked = false;
+
+ fix_rate = (gint) adj->value;
+ printf("fix rate %d\n", fix_rate);
+ }
+}
+
+static void
+cb_accuracy_mask(GtkAdjustment* adj)
+{
+ set_accuracy_mask = true;
+ accuracy_mask = (gint) adj->value;
+ // printf("accuracy_mask %d\n", accuracy_mask);
+}
+
+static void
+cb_timeout(GtkAdjustment* adj)
+{
+ set_timeout = true;
+ timeout = (gint) adj->value;
+ // printf("timeout %d\n", timeout);
+}
+
+int fix_count = 1;
+
+static void cb_fix_count( GtkAdjustment* adj)
+{
+ fix_count = (gint) adj->value;
+ // printf("fix count %d\n", fix_count);
+}
+
+int batch_count = 0;
+
+static void cb_batch_count( GtkAdjustment* adj)
+{
+ batch_count = (gint) adj->value;
+ // printf("batch count %d\n", batch_count);
+}
+
+GtkWidget* wid_batch_count;
+GtkWidget* wid_fix_count;
+
+bool doing_batch = false;
+bool doing_reset_gps = false;
+
+static void cb_batch_allowed(GtkToggleButton* button)
+{
+ printf("batch allowed %d\n", button->active);
+ if (button->active)
+ {
+ gtk_widget_show(wid_batch_count);
+ gtk_widget_show(wid_fix_count);
+ doing_batch = true;
+ }
+ else
+ {
+ gtk_widget_hide(wid_batch_count);
+ gtk_widget_hide(wid_fix_count);
+ doing_batch = false;
+ }
+}
+
+int nmea_log = TRUE;
+GtkToggleButton* wid_log0;
+GtkToggleButton* wid_log1;
+
+static void cb_nmea_log_value( GtkToggleButton* button)
+{
+ nmea_log = button->active;
+ printf("nmea_log %d\n", nmea_log);
+ if (button != wid_log0) gtk_toggle_button_set_active(wid_log0, nmea_log);
+ if (button != wid_log1) gtk_toggle_button_set_active(wid_log1, nmea_log);
+}
+
+int using_simulator = FALSE;
+
+static void cb_simulator_value( GtkToggleButton* button)
+{
+ using_simulator = button->active;
+ printf("simulator %d\n", using_simulator);
+}
+
+int pnd_mode = TRUE;
+GtkToggleButton* wid_pnd0;
+GtkToggleButton* wid_pnd1;
+
+static void cb_pnd_value( GtkToggleButton* button)
+{
+ pnd_mode = button->active;
+ printf("pnd_mode %d\n", pnd_mode);
+ if (button != wid_pnd0) gtk_toggle_button_set_active(wid_pnd0, pnd_mode);
+ if (button != wid_pnd1) gtk_toggle_button_set_active(wid_pnd1, pnd_mode);
+}
+
+/* Convenience functions */
+
+static GtkWidget* make_menu_item(gchar* name, GCallback callback)
+{
+ GtkWidget* item = gtk_menu_item_new_with_label (name);
+ g_signal_connect (G_OBJECT (item), "activate", callback, (gpointer)name);
+ gtk_widget_show (item);
+
+ return item;
+}
+
+void scale_init(GtkScale* scale)
+{
+ gtk_range_set_update_policy (GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
+ gtk_scale_set_digits (scale, 0);
+ gtk_scale_set_value_pos (scale, GTK_POS_RIGHT);
+ gtk_scale_set_draw_value (scale, TRUE);
+}
+
+static void cb_arrow_clicked(GtkButton* b, gpointer user_data)
+{
+ int offset = GPOINTER_TO_INT(user_data);
+ gdouble value = gtk_adjustment_get_value(wid_fix_rate0);
+ printf("arrow click offset %d + %f\n", offset, value);
+
+ value += offset;
+ gtk_adjustment_set_value(wid_fix_rate0, value);
+ gtk_adjustment_set_value(wid_fix_rate1, value);
+ // gtk_button_set_relief(b, GTK_RELIEF_NONE);
+}
+
+static GtkWidget* create_arrow_button(GtkArrowType a, int offset)
+{
+ GtkShadowType s = GTK_SHADOW_ETCHED_OUT;
+
+ GtkWidget* button = gtk_button_new();
+ GtkWidget* arrow = gtk_arrow_new(a, s);
+ gtk_container_add(GTK_CONTAINER(button), arrow);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (cb_arrow_clicked), GINT_TO_POINTER(offset));
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);
+ gtk_widget_show(arrow);
+ gtk_widget_show(button);
+ return button;
+}
+
+GtkWidget* wid_batch_mode = 0;
+GtkWidget* wid_simulator = 0;
+GtkWidget* box_fix_type = 0;
+GtkWidget* wid_fix_box0 = 0;
+GtkWidget* wid_fix_box1 = 0;
+
+// The gllin.cpp calls us
+
+void
+pm_controls_active(bool active)
+{
+ if (box_fix_type) gtk_widget_set_sensitive(box_fix_type, active);
+ if (wid_simulator) gtk_widget_set_sensitive(wid_simulator, active);
+ if (wid_batch_mode)gtk_widget_set_sensitive(wid_batch_mode, active);
+ if (wid_batch_count) gtk_widget_set_sensitive(wid_batch_count, active);
+ if (wid_fix_count) gtk_widget_set_sensitive(wid_fix_count, active);
+ if (wid_log0) gtk_widget_set_sensitive(GTK_WIDGET(wid_log0), active);
+ if (wid_log1) gtk_widget_set_sensitive(GTK_WIDGET(wid_log1), active);
+ if (wid_pnd0) gtk_widget_set_sensitive(GTK_WIDGET(wid_pnd0), active);
+ if (wid_pnd1) gtk_widget_set_sensitive(GTK_WIDGET(wid_pnd1), active);
+ if (wid_fix_box0) gtk_widget_set_sensitive(wid_fix_box0, active);
+ if (wid_fix_box1) gtk_widget_set_sensitive(wid_fix_box1, active);
+ if (wid_box_accuracy_mask) gtk_widget_set_sensitive(wid_box_accuracy_mask, active);
+ if (wid_box_timeout) gtk_widget_set_sensitive(wid_box_timeout, active);
+}
+
+//-----------------------------------------------------------------------------------
+//
+// Direct connection to the batch tests.
+//
+// The NMEA is decoded and these functions are called when
+// a batch test starts, and when a fix is done.
+//
+//-----------------------------------------------------------------------------------
+
+static int real_batch_count;
+static int real_fix_count;
+
+static void
+update_batch_count()
+{
+ gtk_adjustment_set_value(wid_batch_adj, batch_count);
+}
+
+static void
+update_fix_count()
+{
+ gtk_adjustment_set_value(wid_fix_adj, fix_count);
+}
+
+void
+page_pm_batch_start()
+{
+ if (!doing_batch) return;
+ real_batch_count = batch_count;
+ real_fix_count = fix_count;
+ printf("page_pm_batch_start()/%d %d %d\n",
+ __LINE__, real_batch_count, real_fix_count);
+}
+
+void
+page_pm_batch_next()
+{
+ if (!doing_batch) return;
+ fix_count = real_fix_count;
+ --batch_count;
+ printf("page_pm_batch_next()/%d %d %d\n",
+ __LINE__, batch_count, fix_count);
+ update_batch_count();
+ update_fix_count();
+}
+
+void
+page_pm_fix_done()
+{
+ if (!doing_batch) return;
+ --fix_count;
+ update_fix_count();
+ // printf("page_pm_fix_done()/%d %d %d\n", __LINE__, batch_count, fix_count);
+}
+
+void
+page_pm_batch_done()
+{
+ if (!doing_batch) return;
+ batch_count = real_batch_count;
+ fix_count = real_fix_count;
+ printf("page_pm_batch_done()/%d %d %d\n",
+ __LINE__, batch_count, fix_count);
+ update_fix_count();
+ update_batch_count();
+}
+
+//-------------------------------------------------------------------------------------
+//
+// create_range_controls()
+//
+// Create the controls for the "run" and the "test" pages.
+// Some are shared.
+//
+//-------------------------------------------------------------------------------------
+
+void create_range_controls(GtkWidget* window, GtkWidget* table, bool test)
+{
+ GtkWidget* box;
+ GtkObject* adj;
+ GtkWidget* scale;
+ GtkWidget* label;
+
+if (!test)
+{
+ //--------------------------------------------------------------------------
+ // Accuracy Mask
+ //--------------------------------------------------------------------------
+ box = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 0);
+
+ label = gtk_label_new("Accuracy Mask");
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ adj = gtk_adjustment_new ((gdouble) accuracy_mask, 0.0, 1001.0, 1.0, 1.0, 1.0);
+ g_signal_connect (G_OBJECT (adj), "value_changed",
+ G_CALLBACK (cb_accuracy_mask), (gpointer) adj);
+ scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
+ scale_init(GTK_SCALE(scale));
+ gtk_widget_show(scale);
+
+ gtk_box_pack_start (GTK_BOX (box), scale, TRUE, TRUE, 0);
+ //gtk_widget_show(box);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 1, 11, 12);
+ wid_box_accuracy_mask = box;
+
+ //--------------------------------------------------------------------------
+ // Timeout (0..64)
+ // 0 == forever.
+ //--------------------------------------------------------------------------
+ box = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 3);
+
+ label = gtk_label_new ("Timeout");
+ gtk_box_pack_start(GTK_BOX (box), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ adj = gtk_adjustment_new((gdouble) timeout, 0.0, 65.0, 1.0, 1.0, 1.0);
+ g_signal_connect (G_OBJECT (adj), "value_changed",
+ G_CALLBACK (cb_timeout), (gpointer) adj);
+ scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
+ scale_init(GTK_SCALE(scale));
+ gtk_box_pack_start (GTK_BOX (box), scale, TRUE, TRUE, 0);
+ gtk_widget_show(scale);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 1, 2, 11, 12);
+ //gtk_widget_show(box);
+
+ wid_box_timeout = box;
+}
+
+ //--------------------------------------------------------------------------
+ // Logging checkbox (shared)
+ //--------------------------------------------------------------------------
+ box = gtk_hbox_new (FALSE, 6);
+ GtkWidget* button = gtk_check_button_new_with_label("Logging");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), nmea_log);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (cb_nmea_log_value), NULL);
+ gtk_widget_show(button);
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+ if (wid_log0) wid_log1 = GTK_TOGGLE_BUTTON(button);
+ else wid_log0 = GTK_TOGGLE_BUTTON(button);
+
+ //gtk_widget_show(box);
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 1, 2, 12, 13);
+
+ //--------------------------------------------------------------------------
+ // fix rate (0..64 seconds)
+ // 0 == native.
+ //--------------------------------------------------------------------------
+ box = gtk_hbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 0);
+
+ label = gtk_label_new ("Fix rate");
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 2);
+ gtk_widget_show(label);
+
+ button = create_arrow_button(GTK_ARROW_LEFT, -1);
+ gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
+
+ adj = gtk_adjustment_new ((gdouble) fix_rate, 0.0, 64.0, 1.0,
+ 10.0, 10.0);
+ g_signal_connect (G_OBJECT (adj), "value_changed",
+ G_CALLBACK (cb_fix_rate), (gpointer) adj);
+ if (wid_fix_rate0) wid_fix_rate1 = GTK_ADJUSTMENT(adj);
+ else wid_fix_rate0 = GTK_ADJUSTMENT(adj);
+ scale = gtk_hscale_new (GTK_ADJUSTMENT(adj));
+ scale_init(GTK_SCALE(scale));
+ gtk_box_pack_start (GTK_BOX (box), scale, TRUE, TRUE, 0);
+ gtk_widget_show(scale);
+
+ button = create_arrow_button(GTK_ARROW_RIGHT, +1);
+ gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
+
+ if (wid_fix_box0) wid_fix_box1 = box;
+ else wid_fix_box0 = box;
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 1, 12, 13);
+ gtk_widget_show (box);
+
+ if (!test) return;
+
+ //--------------------------------------------------------------------------
+ // Fix start selection
+ // COLD, WARM, HOT, SNR Factory test.
+ // COLD+LTO, WARM+LTO
+ //--------------------------------------------------------------------------
+
+ box = gtk_hbox_new (FALSE, 6);
+ box_fix_type = box;
+ gtk_container_set_border_width (GTK_CONTAINER (box), 3);
+
+ label = gtk_label_new ("Fix type");
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ GtkWidget* opt = gtk_option_menu_new();
+ GtkWidget* menu = gtk_menu_new();
+
+ GtkWidget* item = make_menu_item ("cold", G_CALLBACK (cb_pos_menu_select));
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ item = make_menu_item ("cold (no LTO)", G_CALLBACK (cb_pos_menu_select));
+ gtk_menu_shell_append (GTK_MENU_SHELL(menu), item);
+
+ item = make_menu_item ("warm", G_CALLBACK (cb_pos_menu_select));
+ gtk_menu_shell_append (GTK_MENU_SHELL(menu), item);
+
+ item = make_menu_item ("warm (no LTO)", G_CALLBACK (cb_pos_menu_select));
+ gtk_menu_shell_append (GTK_MENU_SHELL(menu), item);
+
+ item = make_menu_item ("hot", G_CALLBACK (cb_pos_menu_select));
+ gtk_menu_shell_append (GTK_MENU_SHELL(menu), item);
+
+ item = make_menu_item ("SNR", G_CALLBACK (cb_pos_menu_select));
+ gtk_menu_shell_append (GTK_MENU_SHELL(menu), item);
+
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(opt), 4); // [default] is "hot"
+ gtk_box_pack_start (GTK_BOX (box), opt, TRUE, TRUE, 0);
+ gtk_widget_show (opt);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 1, 2, 11, 12);
+ gtk_widget_show (box);
+
+{
+ //--------------------------------------------------------------------------
+ // Number of fixes (1..n)
+ //--------------------------------------------------------------------------
+ box = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 0);
+
+ label = gtk_label_new ("Fix count");
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ adj = gtk_adjustment_new ((gdouble) fix_count, 0.0, 1100.0, 1.0, 1.0, 1.0);
+ g_signal_connect (G_OBJECT (adj), "value_changed",
+ G_CALLBACK (cb_fix_count), (gpointer) adj);
+ wid_fix_adj = GTK_ADJUSTMENT(adj);
+ scale = gtk_hscale_new(wid_fix_adj);
+ scale_init(GTK_SCALE(scale));
+ gtk_box_pack_start (GTK_BOX (box), scale, TRUE, TRUE, 0);
+ gtk_widget_show (scale);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 1, 2, 10, 11);
+ wid_fix_count = box;
+
+ //--------------------------------------------------------------------------
+ // Number of batches (0..n)
+ // 0 == forever.
+ //--------------------------------------------------------------------------
+ box = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 3);
+
+ label = gtk_label_new ("Batches");
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ adj = gtk_adjustment_new((gdouble) batch_count, 0.0, 1100.0, 1.0, 1.0, 1.0);
+ g_signal_connect (G_OBJECT (adj), "value_changed",
+ G_CALLBACK (cb_batch_count), (gpointer) adj);
+ wid_batch_adj = GTK_ADJUSTMENT(adj);
+ scale = gtk_hscale_new(wid_batch_adj);
+ scale_init(GTK_SCALE(scale));
+ gtk_box_pack_start (GTK_BOX (box), scale, TRUE, TRUE, 0);
+ gtk_widget_show (scale);
+
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 1, 10, 11);
+ wid_batch_count = box;
+}
+
+ //--------------------------------------------------------------------------
+ // Batch mode checkbox
+ //--------------------------------------------------------------------------
+ box = gtk_hbox_new (FALSE, 6);
+ button = gtk_check_button_new_with_label("Batch");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (cb_batch_allowed), NULL);
+ gtk_widget_show(button);
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+ wid_batch_mode = button;
+
+ //--------------------------------------------------------------------------
+ // Simulator checkbox
+ //--------------------------------------------------------------------------
+ button = gtk_check_button_new_with_label("Simulator");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), using_simulator);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (cb_simulator_value), NULL);
+ gtk_widget_show(button);
+ gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 1);
+ wid_simulator = button;
+
+ gtk_widget_show(box);
+ gtk_table_attach_defaults(GTK_TABLE (table), box, 0, 1, 11, 12);
+}
+
+
+//------------------------------------------------------------------------------
+//
+// GLLIN parameter setting.
+//
+//------------------------------------------------------------------------------
+
+static int argMax;
+static int argc;
+static const char** argv;
+
+void addArg(const char* s)
+{
+ if (argc < argMax)
+ {
+ argv[ argc] = s;
+ argv[++argc] = 0;
+ }
+}
+
+void addArgInt(int n, char* s)
+{
+ if (argc < argMax)
+ {
+ sprintf(s, "%d", n);
+ addArg(s);
+ }
+}
+
+extern void on_clicked_start(GtkWidget* widget, gpointer data);
+
+void
+pm_controls_nmea_epoch_done(void)
+{
+ // Trigger the stress test change...
+ if (!doing_stress) return;
+
+ if (--stress_count > 0) return;
+
+ printf("pm_controls_nmea_epoch_done/%d %d %d\n",
+ __LINE__, doing_stress, fix_count);
+
+ on_clicked_start(0, 0); // Stop
+ sleep(2); // slight pause for GLLIN to exit.
+
+ if (doing_ptf)
+ {
+ on_clicked_start(0, (gpointer) 1); // Restart (single shot)
+ }
+ else
+ {
+ on_clicked_start(0, 0); // Restart.
+ }
+}
+
+void
+gllin_arg_set(int arg_max, int* pArgc, const char** pp_argv)
+{
+ argc = *pArgc;
+ argMax = arg_max;
+ argv = pp_argv;
+
+ if (doing_reset_gps)
+ {
+ addArg("-recover");
+ *pArgc = argc;
+ return;
+ }
+
+ if (doing_ptf)
+ {
+ addArg("+ptf");
+ static char sTO[8];
+ if (set_timeout)
+ {
+ addArg("-to");
+ addArgInt(set_timeout, sTO);
+ }
+
+ static char sAM[8];
+ if (set_accuracy_mask)
+ {
+ addArg("-am");
+ addArgInt(accuracy_mask, sAM);
+ }
+ }
+ else
+ {
+ static char sFixRate[4];
+ addArg("-periodic"); // Periodic fix rate
+ addArgInt(fix_rate, sFixRate);
+ }
+
+ doing_stress = false;
+
+ if (doing_batch)
+ {
+ int count = fix_count;
+ if (!count)
+ {
+ count = 10 + (rand() & 0xFF);
+ }
+ printf("%s/%d Starting %s test count %d\n", __FILE__, __LINE__,
+ (batch_count) ? "batch" : "stress", count);
+ if (batch_count)
+ {
+ static char sBatchCount[32];
+ static char sFixCount[32];
+
+ addArg("-batch");
+ addArg(start_type);
+ addArgInt(batch_count, sBatchCount);
+ addArgInt(count, sFixCount);
+ }
+ else
+ {
+ doing_stress = true;
+ stress_count = count;
+ }
+ }
+ else
+ {
+ addArg(start_type);
+ }
+
+ if (using_simulator) addArg("+SIM");
+ if (!allow_lto) addArg("-lto");
+ if (nmea_log) addArg("+nmea"); else addArg("-nmea");
+
+ addArg("+np");
+
+ *pArgc = argc;
+}
+
+void
+pm_report(FILE* f, bool stress)
+{
+ if (stress)
+ {
+ if (doing_reset_gps)
+ {
+ fprintf(f, "Reset GPS hardware\n");
+ }
+
+ if (doing_stress)
+ {
+ fprintf(f, "Running stress test. %d fixes%s\n",
+ stress_count,
+ (fix_count) ? "" : " (random)");
+ }
+ if (doing_batch)
+ {
+ fprintf(f, "Running batch test %d x %d (%d x %d remain)\n",
+ real_batch_count, real_fix_count,
+ batch_count, fix_count );
+ }
+ else
+ {
+ fprintf(f, "Not a batch test\n");
+ }
+ }
+ else
+ {
+ if (doing_ptf)
+ {
+ fprintf(f, "Push to fix.\n");
+ if (set_timeout)
+ fprintf(f, "Position fix timeout %d seconds\n", set_timeout);
+ if (set_accuracy_mask)
+ fprintf(f, "Accuracy mask %d meters\n", accuracy_mask);
+ }
+ else if (fix_rate)
+ {
+ if (1 == fix_rate)
+ fprintf(f, "Compute a fix every second\n");
+ else
+ fprintf(f, "Compute a fix every %d seconds\n", fix_rate);
+ }
+ else
+ {
+ fprintf(f, "Compute a fix as fast as possible\n");
+ }
+ if (using_simulator)
+ fprintf(f, "Connected to a GPS simulator.\n");
+ if (!allow_lto)
+ fprintf(f, "LTO is suppressed\n");
+ if (!nmea_log)
+ fprintf(f, "NMEA logging is suppressed\n");
+ }
+
+ if (strcmp(start_type,"hot"))
+ fprintf(f, "Simulate a %s start\n", start_type);
+ else
+ fprintf(f, "Performing a %s start\n", start_type);
+}
Added: developers/olv/openmoko-agpsui2/src/sv_bar.h
===================================================================
--- developers/olv/openmoko-agpsui2/src/sv_bar.h 2007-11-07 15:54:27 UTC (rev 3370)
+++ developers/olv/openmoko-agpsui2/src/sv_bar.h 2007-11-07 17:07:34 UTC (rev 3371)
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2007 Global Locate.
+ *
+ * Written by Ken Yale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef SV_BAR_H__
+#define SV_BAR_H__
+
+enum
+{
+ MIN_ELEVATION = 10, // The smallest legible angle.
+ FONT_WIDTH = 12,
+ FONT_HEIGHT = 20,
+ DB_HZ_to_DBM = -173,
+ N_AVG = 60,
+ MAX_SVS = 14,
+ SEP_WIDTH = 3, // 3 pixels between bars.
+ BAR_HEIGHT = 300, // 300 pixels tall.
+ PIXMAP_WIDTH = 476, // later --- get from the window somwhow.
+ LARGE_WINDOW_WIDTH = PIXMAP_WIDTH - 80,
+ // slightly smaller than LARGE_WINDOW_HEIGHT??
+ DEGREE_64 = 64 // Minimum arc drawing is 1/64 of a degree
+
+};
+
+typedef struct SV_bar
+{
+ int prn;
+ int ss;
+ int ss_max;
+ int ss_min;
+ int az;
+ int el;
+ bool use;
+ int avg[N_AVG];
+ int nAvg;
+ int sumAvg;
+ int indexAvg;
+ unsigned long lastUpdate;
+ unsigned long ss_max_time;
+ unsigned long ss_min_time;
+
+ void init()
+ {
+ nAvg = 0;
+ sumAvg = 0;
+ indexAvg = 0;
+ use = false;
+ ss_max = 0;
+ ss_max_time = 0;
+ ss_min = 60;
+ ss_min_time = 0;
+ };
+
+ void add_ss()
+ {
+ if (++indexAvg >= N_AVG)
+ {
+ indexAvg = 0;
+ }
+ if (++nAvg > N_AVG)
+ {
+ sumAvg -= avg[indexAvg];
+ }
+ avg[indexAvg] = ss;
+ sumAvg += ss;
+ };
+
+ int avg_ss()
+ {
+ if (!use) return 0;
+ if (nAvg < 1) return 0;
+ if (nAvg < N_AVG) return sumAvg/nAvg;
+ return (sumAvg - 1 + N_AVG/2) / N_AVG;
+ };
+
+ // Return a number between -100 and +100 along the X and Y axes.
+ void get_xy(int&x, int& y);
+ static int scale_radius(int r);
+
+ static int nSS;
+ static bool changed;
+ static int leastSamplesAveraged;
+};
+
+extern SV_bar bars[MAX_SVS];
+
+#endif
More information about the commitlog
mailing list