kopia lustrzana https://github.com/rs1729/RS
update/merge master->test, except multi
rodzic
6a20bed8f9
commit
d041c35591
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. 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
|
||||
them 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 prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. 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.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey 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;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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 that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
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.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
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.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
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
|
||||
state 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program 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, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU 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 Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
@ -327,8 +327,8 @@ static void printJSON() {
|
|||
if (gpx.sn) {
|
||||
sprintf(json_sonde_id, "C50-%u", gpx.sn);
|
||||
}
|
||||
printf("{ ");
|
||||
printf("\"id\": \"%s\", ", json_sonde_id);
|
||||
printf("{ \"type\": \"%s\"", "C50");
|
||||
printf(", \"id\": \"%s\", ", json_sonde_id);
|
||||
printf("\"datetime\": \"%04d-%02d-%02dT%02d:%02d:%02dZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.1f",
|
||||
gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt);
|
||||
if (option_ptu && (gpx.T > -273.0 || gpx.RH > -0.5)) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
|
||||
## Radiosonde decoders
|
||||
|
||||
alternative decoders using cross-correlation for better header-synchronization
|
||||
alternative decoders using cross-correlation for better header-synchronization <br />
|
||||
NOTE: more recent decoders are here: [RS/demod/mod/](https://github.com/rs1729/RS/tree/master/demod/mod)
|
||||
|
||||
|
||||
#### Files
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ alternative decoders using cross-correlation for better header-synchronization
|
|||
#### Files
|
||||
|
||||
* `demod_mod.c`, `demod_mod.h`, <br />
|
||||
`rs41mod.c`, `rs92mod.c`, `dfm09mod.c`, `m10mod.c`, `lms6mod.c`, <br />
|
||||
`rs41mod.c`, `rs92mod.c`, `dfm09mod.c`, `m10mod.c`, `lms6mod.c`, `lms6Xmod.c`, `meisei100mod.c`, <br />
|
||||
`bch_ecc_mod.c`, `bch_ecc_mod.h`
|
||||
|
||||
#### Compile
|
||||
|
@ -15,13 +15,48 @@ alternative decoders using cross-correlation for better header-synchronization
|
|||
`gcc rs41mod.c demod_mod.o bch_ecc_mod.o -lm -o rs41mod` <br />
|
||||
`gcc dfm09mod.c demod_mod.o -lm -o dfm09mod` <br />
|
||||
`gcc m10mod.c demod_mod.o -lm -o m10mod` <br />
|
||||
`gcc lms6mod.c demod_mod.o -lm -o lms6mod` <br />
|
||||
`gcc lms6Xmod.c demod_mod.o bch_ecc_mod.o -lm -o lms6Xmod` <br />
|
||||
`gcc meisei100mod.c demod_mod.o bch_ecc_mod.o -lm -o meisei100mod` <br />
|
||||
`gcc rs92mod.c demod_mod.o bch_ecc_mod.o -lm -o rs92mod` (needs `RS/rs92/nav_gps_vel.c`)
|
||||
|
||||
#### Usage/Examples
|
||||
`./rs41mod --ecc2 --crc -vx --ptu <audio.wav>` <br />
|
||||
`./dfm09mod --ecc -v --ptu <audio.wav>` (add `-i` for dfm06)<br />
|
||||
`./rs41mod --ecc2 -vx --ptu <audio.wav>` <br />
|
||||
`./dfm09mod --ecc -v --ptu <audio.wav>` (add `-i` for dfm06; or use `--auto`) <br />
|
||||
`./m10mod --dc -vv --ptu -c <audio.wav>` <br />
|
||||
`./lms6mod --vit --ecc -v <audio.wav>` <br />
|
||||
`./lms6Xmod --vit --ecc -v <audio.wav>` <br />
|
||||
|
||||
IQ data:<br />
|
||||
If the IQ data is downsampled and centered (IF band), use <br />
|
||||
`./rs41mod --iq2 <iq_data.wav>` <br />
|
||||
or with lowpass filter <br />
|
||||
`./rs41mod --iq2 --lp <iq_data.wav>` <br />
|
||||
For baseband IQ data, use
|
||||
`./rs41mod --IQ <fq> <iq_data.wav>` <br />
|
||||
where `<fq>` is the relative frequency in `-0.5 .. 0.5`;
|
||||
e.g. if the receiver is tuned to 403MHz and the (complex) sample rate is 2MHz,
|
||||
a signal at 402.5MHz would be -0.5MHz off, i.e. `<fq> = -0.5/2 = -0.25`. <br />
|
||||
For IQ data (i.e. 2 channels) it is possible to read raw data (without wav header): <br />
|
||||
`./rs41mod --IQ <fq> - <sr> <bs> <iq_data.raw>` <br />
|
||||
`<sr>`: sample rate <br />
|
||||
`<bs>=8,16,32`: bits per (real) sample (u8, s16 or f32)
|
||||
|
||||
#### Remarks
|
||||
FM-demodulation is sensitive to noise at higher frequencies. A narrow low-pass filter is needed before demodulation.
|
||||
For weak signals and higher modulation indices IQ-decoding is usually better.
|
||||
<br />
|
||||
|
||||
DFM:<br />
|
||||
The high modulation index has advantages in IQ-decoding. <br />
|
||||
`--ecc2` uses soft decision for 2-error words. If weak signals frequently produce errors, it is likely that
|
||||
more than 2 errors occur in a received word. Since there is no additional frame protection (e.g. CRC), the
|
||||
frames will not be decoded reliably in weak conditions. The `--dist` option has a thredshold for the number
|
||||
of errors per packet.
|
||||
<br />
|
||||
|
||||
LMS6-403:<br />
|
||||
`lms6Xmod_soft.c` (testing) provides a soft viterbi decoding option `--vit2`;
|
||||
IQ-decoding is recommended for soft decoding (noisy/spikey FM-signals don't always help soft decision).
|
||||
The difference between hard and soft viterbi becomes only apparent at lower SNR. The inner convolutional
|
||||
code does most of the error correction. The concatenated outer Reed-Solomon code kicks in only at low SNR.
|
||||
|
||||
|
||||
|
|
|
@ -42,35 +42,35 @@ typedef struct {
|
|||
} RS_t;
|
||||
|
||||
|
||||
static GF_t GF256RS = { f : 0x11D, // RS-GF(2^8): X^8 + X^4 + X^3 + X^2 + 1 : 0x11D
|
||||
ord : 256, // 2^8
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF256RS = { .f = 0x11D, // RS-GF(2^8): X^8 + X^4 + X^3 + X^2 + 1 : 0x11D
|
||||
.ord = 256, // 2^8
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF256RSccsds = { f : 0x187, // RS-GF(2^8): X^8 + X^7 + X^2 + X + 1 : 0x187
|
||||
ord : 256, // 2^8
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF256RSccsds = { .f = 0x187, // RS-GF(2^8): X^8 + X^7 + X^2 + X + 1 : 0x187
|
||||
.ord = 256, // 2^8
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF64BCH = { f : 0x43, // BCH-GF(2^6): X^6 + X + 1 : 0x43
|
||||
ord : 64, // 2^6
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF64BCH = { .f = 0x43, // BCH-GF(2^6): X^6 + X + 1 : 0x43
|
||||
.ord = 64, // 2^6
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF16RS = { f : 0x13, // RS-GF(2^4): X^4 + X + 1 : 0x13
|
||||
ord : 16, // 2^4
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF16RS = { .f = 0x13, // RS-GF(2^4): X^4 + X + 1 : 0x13
|
||||
.ord = 16, // 2^4
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF256AES = { f : 0x11B, // AES-GF(2^8): X^8 + X^4 + X^3 + X + 1 : 0x11B
|
||||
ord : 256, // 2^8
|
||||
alpha: 0x03, // generator: alpha = X+1
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF256AES = { .f = 0x11B, // AES-GF(2^8): X^8 + X^4 + X^3 + X + 1 : 0x11B
|
||||
.ord = 256, // 2^8
|
||||
.alpha = 0x03, // generator: alpha = X+1
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
|
||||
static RS_t RS256 = { 255, 12, 24, 231, 0, 1, 1, {0}, {0} };
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
* sync header: correlation/matched filter
|
||||
* compile:
|
||||
* gcc -c demod_mod.c
|
||||
* speedup:
|
||||
* gcc -O2 -c demod_mod.c
|
||||
* or
|
||||
* gcc -Ofast -c demod_mod.c
|
||||
*
|
||||
* author: zilog80
|
||||
*/
|
||||
|
@ -509,7 +513,7 @@ static int lowpass_init(float f, int taps, float **pws) {
|
|||
|
||||
h = (double*)calloc( taps+1, sizeof(double)); if (h == NULL) return -1;
|
||||
w = (double*)calloc( taps+1, sizeof(double)); if (w == NULL) return -1;
|
||||
ws = (float*)calloc( taps+1, sizeof(float)); if (ws == NULL) return -1;
|
||||
ws = (float*)calloc( 2*taps+1, sizeof(float)); if (ws == NULL) return -1;
|
||||
|
||||
for (n = 0; n < taps; n++) {
|
||||
w[n] = 7938/18608.0 - 9240/18608.0*cos(2*M_PI*n/(taps-1)) + 1430/18608.0*cos(4*M_PI*n/(taps-1)); // Blackmann
|
||||
|
@ -520,6 +524,9 @@ static int lowpass_init(float f, int taps, float **pws) {
|
|||
for (n = 0; n < taps; n++) {
|
||||
ws[n] /= norm; // 1-norm
|
||||
}
|
||||
|
||||
for (n = 0; n < taps; n++) ws[taps+n] = ws[n]; // duplicate/unwrap
|
||||
|
||||
*pws = ws;
|
||||
|
||||
free(h); h = NULL;
|
||||
|
@ -551,13 +558,15 @@ static int lowpass_update(float f, int taps, float *ws) {
|
|||
ws[n] /= norm; // 1-norm
|
||||
}
|
||||
|
||||
for (n = 0; n < taps; n++) ws[taps+n] = ws[n];
|
||||
|
||||
free(h); h = NULL;
|
||||
free(w); w = NULL;
|
||||
|
||||
return taps;
|
||||
}
|
||||
|
||||
static float complex lowpass(float complex buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
static float complex lowpass0(float complex buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
ui32_t n;
|
||||
double complex w = 0;
|
||||
for (n = 0; n < taps; n++) {
|
||||
|
@ -565,8 +574,18 @@ static float complex lowpass(float complex buffer[], ui32_t sample, ui32_t taps,
|
|||
}
|
||||
return (float complex)w;
|
||||
}
|
||||
static float complex lowpass(float complex buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
ui32_t n;
|
||||
ui32_t s = sample % taps;
|
||||
double complex w = 0;
|
||||
for (n = 0; n < taps; n++) {
|
||||
w += buffer[n]*ws[taps+s-n]; // ws[taps+s-n] = ws[(taps+sample-n)%taps]
|
||||
}
|
||||
return (float complex)w;
|
||||
// symmetry: ws[n] == ws[taps-1-n]
|
||||
}
|
||||
|
||||
static float re_lowpass(float buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
static float re_lowpass0(float buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
ui32_t n;
|
||||
double w = 0;
|
||||
for (n = 0; n < taps; n++) {
|
||||
|
@ -574,6 +593,15 @@ static float re_lowpass(float buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
|||
}
|
||||
return (float)w;
|
||||
}
|
||||
static float re_lowpass(float buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
ui32_t n;
|
||||
ui32_t s = sample % taps;
|
||||
double w = 0;
|
||||
for (n = 0; n < taps; n++) {
|
||||
w += buffer[n]*ws[taps+s-n]; // ws[taps+s-n] = ws[(taps+sample-n)%taps]
|
||||
}
|
||||
return (float)w;
|
||||
}
|
||||
|
||||
|
||||
int f32buf_sample(dsp_t *dsp, int inv) {
|
||||
|
@ -807,7 +835,7 @@ int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spi
|
|||
}
|
||||
sample -= dc;
|
||||
|
||||
if ( l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum -= sample;
|
||||
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum -= sample;
|
||||
|
||||
dsp->sc++;
|
||||
} while (dsp->sc < bg); // n < dsp->sps
|
||||
|
@ -825,9 +853,9 @@ int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spi
|
|||
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
|
||||
sample = avg + scale*(sample - avg); // spikes
|
||||
}
|
||||
sample -= dc;
|
||||
sample -= dc;
|
||||
|
||||
if ( l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum += sample;
|
||||
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum += sample;
|
||||
|
||||
dsp->sc++;
|
||||
} while (dsp->sc < bg); // n < dsp->sps
|
||||
|
@ -839,6 +867,81 @@ int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spi
|
|||
return 0;
|
||||
}
|
||||
|
||||
int read_softbit(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike) {
|
||||
// symlen==2: manchester2 10->0,01->1: 2.bit
|
||||
|
||||
float sample;
|
||||
float avg;
|
||||
float ths = 0.5, scale = 0.27;
|
||||
|
||||
double sum = 0.0;
|
||||
double mid;
|
||||
//double l = 1.0;
|
||||
|
||||
double bg = pos*dsp->symlen*dsp->sps;
|
||||
double dc = 0.0;
|
||||
|
||||
ui8_t bit = 0;
|
||||
|
||||
|
||||
if (dsp->opt_dc && dsp->opt_iq < 2) dc = dsp->dc;
|
||||
|
||||
if (pos == 0) {
|
||||
bg = 0;
|
||||
dsp->sc = 0;
|
||||
}
|
||||
|
||||
|
||||
if (dsp->symlen == 2) {
|
||||
mid = bg + (dsp->sps-1)/2.0;
|
||||
bg += dsp->sps;
|
||||
do {
|
||||
if (dsp->buffered > 0) dsp->buffered -= 1;
|
||||
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
|
||||
|
||||
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
|
||||
if (spike && fabs(sample - avg) > ths) {
|
||||
avg = 0.5*(dsp->bufs[(dsp->sample_out-dsp->buffered-1 + ofs + dsp->M) % dsp->M]
|
||||
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
|
||||
sample = avg + scale*(sample - avg); // spikes
|
||||
}
|
||||
sample -= dc;
|
||||
|
||||
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum -= sample;
|
||||
|
||||
dsp->sc++;
|
||||
} while (dsp->sc < bg); // n < dsp->sps
|
||||
}
|
||||
|
||||
mid = bg + (dsp->sps-1)/2.0;
|
||||
bg += dsp->sps;
|
||||
do {
|
||||
if (dsp->buffered > 0) dsp->buffered -= 1;
|
||||
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
|
||||
|
||||
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
|
||||
if (spike && fabs(sample - avg) > ths) {
|
||||
avg = 0.5*(dsp->bufs[(dsp->sample_out-dsp->buffered-1 + ofs + dsp->M) % dsp->M]
|
||||
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
|
||||
sample = avg + scale*(sample - avg); // spikes
|
||||
}
|
||||
sample -= dc;
|
||||
|
||||
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum += sample;
|
||||
|
||||
dsp->sc++;
|
||||
} while (dsp->sc < bg); // n < dsp->sps
|
||||
|
||||
|
||||
if (sum >= 0) bit = 1;
|
||||
else bit = 0;
|
||||
|
||||
shb->hb = bit;
|
||||
shb->sb = (float)sum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define IF_SAMPLE_RATE 48000
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
#include <math.h>
|
||||
#include <complex.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.1415926535897932384626433832795)
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned char ui8_t;
|
||||
typedef unsigned short ui16_t;
|
||||
typedef unsigned int ui32_t;
|
||||
|
@ -133,10 +138,17 @@ typedef struct {
|
|||
} pcm_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ui8_t hb;
|
||||
float sb;
|
||||
} hsbit_t;
|
||||
|
||||
|
||||
|
||||
float read_wav_header(pcm_t *, FILE *);
|
||||
int f32buf_sample(dsp_t *, int);
|
||||
int read_slbit(dsp_t *, int*, int, int, int, float, int);
|
||||
int read_softbit(dsp_t *, hsbit_t *, int, int, int, float, int );
|
||||
|
||||
int init_buffers(dsp_t *);
|
||||
int free_buffers(dsp_t *);
|
||||
|
|
|
@ -68,7 +68,7 @@ typedef struct {
|
|||
float status[2];
|
||||
float _frmcnt;
|
||||
char sonde_id[16]; // "ID__:xxxxxxxx\0\0"
|
||||
char frame_bits[BITFRAME_LEN+4];
|
||||
hsbit_t frame[BITFRAME_LEN+4]; // char frame_bits[BITFRAME_LEN+4];
|
||||
char dat_str[9][13+1];
|
||||
sn_t snc;
|
||||
pcksts_t pck[9];
|
||||
|
@ -98,6 +98,15 @@ static char dfm_header[] = "0100010111001111";
|
|||
#define DAT2 (16+160) // 104 bit
|
||||
// frame: 280 bit
|
||||
|
||||
static ui8_t G[8][4] = // Generator
|
||||
{{ 1, 0, 0, 0},
|
||||
{ 0, 1, 0, 0},
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 1},
|
||||
{ 0, 1, 1, 1},
|
||||
{ 1, 0, 1, 1},
|
||||
{ 1, 1, 0, 1},
|
||||
{ 1, 1, 1, 0}};
|
||||
static ui8_t H[4][8] = // Parity-Check
|
||||
{{ 0, 1, 1, 1, 1, 0, 0, 0},
|
||||
{ 1, 0, 1, 1, 0, 1, 0, 0},
|
||||
|
@ -105,6 +114,28 @@ static ui8_t H[4][8] = // Parity-Check
|
|||
{ 1, 1, 1, 0, 0, 0, 0, 1}};
|
||||
static ui8_t He[8] = { 0x7, 0xB, 0xD, 0xE, 0x8, 0x4, 0x2, 0x1}; // Spalten von H:
|
||||
// 1-bit-error-Syndrome
|
||||
static ui8_t codewords[16][8]; // (valid) Hamming codewords
|
||||
|
||||
static int nib4bits(ui8_t nib, ui8_t *bits) { // big endian
|
||||
int j;
|
||||
|
||||
nib &= 0xF;
|
||||
for (j = 0; j < 4; j++) {
|
||||
bits[j] = (nib>>(3-j)) & 0x1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gencode(ui8_t msg[4], ui8_t code[8]) {
|
||||
int i, j; // Gm=c
|
||||
for (i = 0; i < 8; i++) {
|
||||
code[i] = 0;
|
||||
for (j = 0; j < 4; j++) {
|
||||
code[i] ^= G[i][j] & msg[j];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ui32_t bits2val(ui8_t *bits, int len) { // big endian
|
||||
int j;
|
||||
|
@ -117,18 +148,16 @@ static ui32_t bits2val(ui8_t *bits, int len) { // big endian
|
|||
return val;
|
||||
}
|
||||
|
||||
static void deinterleave(char *str, int L, ui8_t *block) {
|
||||
static void deinterleave(hsbit_t *str, int L, hsbit_t *block) {
|
||||
int i, j;
|
||||
for (j = 0; j < B; j++) { // L = 7, 13
|
||||
for (i = 0; i < L; i++) {
|
||||
if (str[L*j+i] >= 0x30 && str[L*j+i] <= 0x31) {
|
||||
block[B*i+j] = str[L*j+i] - 0x30; // ASCII -> bit
|
||||
}
|
||||
block[B*i+j] = str[L*j+i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int check(ui8_t code[8]) {
|
||||
static int check(int opt_ecc, hsbit_t code[8]) {
|
||||
int i, j; // Bei Demodulierung durch Nulldurchgaenge, wenn durch Fehler ausser Takt,
|
||||
ui32_t synval = 0; // verschieben sich die bits. Fuer Hamming-Decode waere es besser,
|
||||
ui8_t syndrom[4]; // sync zu Beginn mit Header und dann Takt beibehalten fuer decision.
|
||||
|
@ -137,7 +166,7 @@ static int check(ui8_t code[8]) {
|
|||
for (i = 0; i < 4; i++) { // S = 4
|
||||
syndrom[i] = 0;
|
||||
for (j = 0; j < 8; j++) { // B = 8
|
||||
syndrom[i] ^= H[i][j] & code[j];
|
||||
syndrom[i] ^= H[i][j] & code[j].hb;
|
||||
}
|
||||
}
|
||||
synval = bits2val(syndrom, 4);
|
||||
|
@ -151,22 +180,67 @@ static int check(ui8_t code[8]) {
|
|||
}
|
||||
}
|
||||
else ret = 0;
|
||||
if (ret > 0) code[ret-1] ^= 0x1;
|
||||
|
||||
if (ret > 0) code[ret-1].hb ^= 0x1; // d=1: 1-bit-error
|
||||
else if (ret < 0 && opt_ecc == 2) { // d=2: 2-bit-error: soft decision
|
||||
// Hamming(8,4)
|
||||
// 256 words:
|
||||
// 16 codewords
|
||||
// 16*8=128 1-error words (dist=1)
|
||||
// 16*7=112 2-error words (dist=2)
|
||||
// each 2-error word has 4 codewords w/ dist=2,
|
||||
// choose best match/correlation
|
||||
int n;
|
||||
int maxn = -1;
|
||||
int d = 0;
|
||||
float sum = 0.0;
|
||||
float maxsum = 0.0;
|
||||
/*
|
||||
sum = 0.0; // s<0: h=0 , s>0: h=1
|
||||
for (i = 0; i < 8; i++) { // h\in{0,1} -> 2h-1\in{-1,+1}
|
||||
sum += (2*code[i].hb-1)*code[i].sb; // i.e. sum_i |s_i|
|
||||
} // original score
|
||||
*/
|
||||
for (n = 0; n < 16; n++) {
|
||||
d = 0;
|
||||
for (i = 0; i < 8; i++) { // d(a,b) = sum_i a[i]^b[i]
|
||||
if (code[i].hb != codewords[n][i]) d++;
|
||||
}
|
||||
if (d == 2) { // check dist=2 codewords - in principle, all codewords could be tested
|
||||
// softbits correlation:
|
||||
// - interleaving
|
||||
// + no pulse-shaping -> sum
|
||||
sum = 0.0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
sum += (2*codewords[n][i]-1) * code[i].sb;
|
||||
}
|
||||
if (sum >= maxsum) { // best match
|
||||
maxsum = sum;
|
||||
maxn = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (maxn >= 0) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (code[i].hb = codewords[maxn][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hamming(int opt_ecc, ui8_t *ham, int L, ui8_t *sym) {
|
||||
static int hamming(int opt_ecc, hsbit_t *ham, int L, ui8_t *sym) {
|
||||
int i, j;
|
||||
int ecc = 0, ret = 0; // L = 7, 13
|
||||
for (i = 0; i < L; i++) { // L * 2 nibble (data+parity)
|
||||
if (opt_ecc) {
|
||||
ecc = check(ham+B*i);
|
||||
ecc = check(opt_ecc, ham+B*i);
|
||||
if (ecc > 0) ret |= (1<<i);
|
||||
if (ecc < 0) ret |= ecc; // -1
|
||||
}
|
||||
for (j = 0; j < S; j++) { // systematic: bits 0..S-1 data
|
||||
sym[S*i+j] = ham[B*i+j];
|
||||
sym[S*i+j] = ham[B*i+j].hb;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -474,17 +548,15 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) {
|
|||
SN6 = bits2val(conf_bits+4, 4*6); // DFM-06: Kanal 6
|
||||
if (SN6 == gpx->SN6 && SN6 != 0) { // nur Nibble-Werte 0..9
|
||||
gpx->sonde_typ = SNbit | 6;
|
||||
gpx->ptu_out = 6;
|
||||
gpx->ptu_out = 6; // <-> DFM-06
|
||||
sprintf(gpx->sonde_id, "ID06:%6X", gpx->SN6);
|
||||
//sprintf(json_sonde_id, "DFM06-%6X", gpx->SN6);
|
||||
}
|
||||
else { // reset
|
||||
gpx->sonde_typ = 0;
|
||||
//sprintf(json_sonde_id, "DFMxx-xxxxxxxx"); //json_sonde_id[0] = '\0';
|
||||
}
|
||||
gpx->SN6 = SN6;
|
||||
}
|
||||
else if ( (sn2_ch & 0xF) == 0xC // 0xsCaaaab, s==sn_ch , s: 0xA=DFM-09 , 0xC=DFM-17? 0xD=?
|
||||
} // SN in last pck/channel, #{pcks} depends on (sensor) config; observed:
|
||||
else if ( (sn2_ch & 0xF) == 0xC // 0xsCaaaab, s==sn_ch , s: 0xA=DFM-09 , 0xC=DFM-09P , 0xB=DFM-17 , 0xD=DFM-17P?
|
||||
|| (sn2_ch & 0xF) == 0x0 ) // 0xs0aaaab, s==sn_ch , s: 0x7,0x8: pilotsonde PS-15?
|
||||
{
|
||||
val = bits2val(conf_bits+8, 4*5);
|
||||
|
@ -507,23 +579,22 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) {
|
|||
gpx->sonde_typ = SNbit | sn_ch;
|
||||
gpx->SN = SN;
|
||||
|
||||
if (sn_ch == 0xA /*&& (sn2_ch & 0xF) == 0xC*/) gpx->ptu_out = sn_ch; else gpx->ptu_out = 0;
|
||||
if (sn_ch == 0xC) gpx->ptu_out = sn_ch;// DFM-09P, DFM-17 ?
|
||||
if (sn_ch == 0xD && gpx->option.dbg) gpx->ptu_out = sn_ch;// DFM-17 (P?)? test 0xD ...?
|
||||
// PS-15 ? (sn2_ch & 0xF) == 0x0 : gpx->ptu_out = 0
|
||||
gpx->ptu_out = 0;
|
||||
if (sn_ch == 0xA /*&& (sn2_ch & 0xF) == 0xC*/) gpx->ptu_out = sn_ch; // <+> DFM-09
|
||||
if (sn_ch == 0xB /*&& (sn2_ch & 0xF) == 0xC*/) gpx->ptu_out = sn_ch; // <-> DFM-17
|
||||
if (sn_ch == 0xC) gpx->ptu_out = sn_ch; // <+> DFM-09P(?)
|
||||
if (sn_ch == 0xD) gpx->ptu_out = sn_ch; // <-> DFM-17P?
|
||||
// PS-15 ? (sn2_ch & 0xF) == 0x0 : gpx->ptu_out = 0 // <-> PS-15
|
||||
|
||||
if ( (gpx->sonde_typ & 0xF) == 0xA) {
|
||||
sprintf(gpx->sonde_id, "ID09:%6u", gpx->SN);
|
||||
//sprintf(json_sonde_id, "DFM09-%6u", gpx->SN);
|
||||
}
|
||||
else {
|
||||
sprintf(gpx->sonde_id, "ID-%1X:%6u", gpx->sonde_typ & 0xF, gpx->SN);
|
||||
//sprintf(json_sonde_id, "DFMx%1X-%6u", gpx->sonde_typ & 0xF,gpx->SN);
|
||||
}
|
||||
}
|
||||
else { // reset
|
||||
gpx->sonde_typ = 0;
|
||||
//sprintf(json_sonde_id, "DFMxx-xxxxxxxx"); //json_sonde_id[0] = '\0';
|
||||
}
|
||||
gpx->snc.SN_X = SN;
|
||||
gpx->snc.chXbit = 0;
|
||||
|
@ -564,6 +635,11 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) {
|
|||
gpx->status[1] = val/100.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gpx->status[0] = 0;
|
||||
gpx->status[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -643,7 +719,7 @@ static void print_gpx(gpx_t *gpx) {
|
|||
|
||||
}
|
||||
}
|
||||
if (gpx->option.vbs == 3 && (gpx->ptu_out == 0xA || gpx->ptu_out >= 0xC)) {
|
||||
if (gpx->option.vbs == 3 && gpx->ptu_out >= 0xA) {
|
||||
printf(" U: %.2fV ", gpx->status[0]);
|
||||
printf(" Ti: %.1fK ", gpx->status[1]);
|
||||
}
|
||||
|
@ -660,22 +736,28 @@ static void print_gpx(gpx_t *gpx) {
|
|||
if (gpx->option.jsn && jsonout)
|
||||
{
|
||||
// JSON Buffer to store sonde ID
|
||||
char json_sonde_id[] = "DFMxx-xxxxxxxx\0\0";
|
||||
switch (gpx->sonde_typ & 0xF) {
|
||||
case 0: sprintf(json_sonde_id, "DFMxx-xxxxxxxx"); break; //json_sonde_id[0] = '\0';
|
||||
case 6: sprintf(json_sonde_id, "DFM06-%6X", gpx->SN6); break;
|
||||
case 0xA: sprintf(json_sonde_id, "DFM09-%6u", gpx->SN); break;
|
||||
// 0x7: PS-15?, 0xC: DFM-17? (0xD: DFM-17?p)
|
||||
default : sprintf(json_sonde_id, "DFMx%1X-%6u", gpx->sonde_typ & 0xF,gpx->SN);
|
||||
char json_sonde_id[] = "DFM-xxxxxxxx\0\0";
|
||||
ui8_t dfm_typ = (gpx->sonde_typ & 0xF);
|
||||
switch ( dfm_typ ) {
|
||||
case 0: sprintf(json_sonde_id, "DFM-xxxxxxxx"); break; //json_sonde_id[0] = '\0';
|
||||
case 6: sprintf(json_sonde_id, "DFM-%6X", gpx->SN6); break; // DFM-06
|
||||
case 0xA: sprintf(json_sonde_id, "DFM-%6u", gpx->SN); break; // DFM-09
|
||||
// 0x7:PS-15?, 0xB:DFM-17? 0xC:DFM-09P? 0xD:DFM-17P?
|
||||
default : sprintf(json_sonde_id, "DFM-%6u", gpx->SN);
|
||||
}
|
||||
|
||||
// Print JSON blob // valid sonde_ID?
|
||||
printf("{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
printf("{ \"type\": \"%s\"", "DFM");
|
||||
printf(", \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
gpx->frnr, json_sonde_id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->horiV, gpx->dir, gpx->vertV);
|
||||
if (gpx->ptu_out >= 0xA && gpx->status[0] > 0) { // DFM>=09(P): Battery (STM32)
|
||||
printf(", \"batt\": %.2f", gpx->status[0]);
|
||||
}
|
||||
if (gpx->ptu_out) { // get temperature
|
||||
float t = get_Temp(gpx); // ecc-valid temperature?
|
||||
if (t > -270.0) printf(", \"temp\": %.1f", t);
|
||||
}
|
||||
if (dfm_typ > 0) printf(", \"subtype\": \"0x%1X\"", dfm_typ);
|
||||
printf(" }\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -692,17 +774,17 @@ static int print_frame(gpx_t *gpx) {
|
|||
int ret0, ret1, ret2;
|
||||
int ret = 0;
|
||||
|
||||
ui8_t hamming_conf[ 7*B]; // 7*8=56
|
||||
ui8_t hamming_dat1[13*B]; // 13*8=104
|
||||
ui8_t hamming_dat2[13*B];
|
||||
hsbit_t hamming_conf[ 7*B]; // 7*8=56
|
||||
hsbit_t hamming_dat1[13*B]; // 13*8=104
|
||||
hsbit_t hamming_dat2[13*B];
|
||||
|
||||
ui8_t block_conf[ 7*S]; // 7*4=28
|
||||
ui8_t block_dat1[13*S]; // 13*4=52
|
||||
ui8_t block_dat2[13*S];
|
||||
|
||||
deinterleave(gpx->frame_bits+CONF, 7, hamming_conf);
|
||||
deinterleave(gpx->frame_bits+DAT1, 13, hamming_dat1);
|
||||
deinterleave(gpx->frame_bits+DAT2, 13, hamming_dat2);
|
||||
deinterleave(gpx->frame+CONF, 7, hamming_conf);
|
||||
deinterleave(gpx->frame+DAT1, 13, hamming_dat1);
|
||||
deinterleave(gpx->frame+DAT2, 13, hamming_dat2);
|
||||
|
||||
ret0 = hamming(gpx->option.ecc, hamming_conf, 7, block_conf);
|
||||
ret1 = hamming(gpx->option.ecc, hamming_dat1, 13, block_dat1);
|
||||
|
@ -751,14 +833,14 @@ static int print_frame(gpx_t *gpx) {
|
|||
}
|
||||
else if (gpx->option.ecc) {
|
||||
|
||||
if (ret0 == 0 || ret0 > 0) {
|
||||
if (ret0 == 0 || ret0 > 0 || gpx->option.ecc == 2) {
|
||||
conf_out(gpx, block_conf, ret0);
|
||||
}
|
||||
if (ret1 == 0 || ret1 > 0) {
|
||||
if (ret1 == 0 || ret1 > 0 || gpx->option.ecc == 2) {
|
||||
frid = dat_out(gpx, block_dat1, ret1);
|
||||
if (frid == 8) print_gpx(gpx);
|
||||
}
|
||||
if (ret2 == 0 || ret2 > 0) {
|
||||
if (ret2 == 0 || ret2 > 0 || gpx->option.ecc == 2) {
|
||||
frid = dat_out(gpx, block_dat2, ret2);
|
||||
if (frid == 8) print_gpx(gpx);
|
||||
}
|
||||
|
@ -856,6 +938,7 @@ int main(int argc, char **argv) {
|
|||
int option_dc = 0;
|
||||
int option_bin = 0;
|
||||
int option_json = 0; // JSON blob output (for auto_rx)
|
||||
int option_pcmraw = 0;
|
||||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int spike = 0;
|
||||
|
@ -866,7 +949,7 @@ int main(int argc, char **argv) {
|
|||
int ret = 0;
|
||||
int k;
|
||||
|
||||
int bit;
|
||||
hsbit_t hsbit;
|
||||
int bitpos = 0;
|
||||
int bitQ;
|
||||
int pos;
|
||||
|
@ -926,7 +1009,8 @@ int main(int argc, char **argv) {
|
|||
else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) {
|
||||
option_inv = 0x1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--ecc") == 0) ) { option_ecc = 1; }
|
||||
else if ( (strcmp(*argv, "--ecc" ) == 0) ) { option_ecc = 1; }
|
||||
else if ( (strcmp(*argv, "--ecc2") == 0) ) { option_ecc = 2; }
|
||||
else if ( (strcmp(*argv, "--ptu") == 0) ) {
|
||||
option_ptu = 1;
|
||||
//gpx.ptu_out = 1; // force ptu (non PS-15)
|
||||
|
@ -974,10 +1058,26 @@ int main(int argc, char **argv) {
|
|||
option_min = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--dbg") == 0) { gpx.option.dbg = 1; }
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
if (*argv) sample_rate = atoi(*argv); else return -1;
|
||||
++argv;
|
||||
if (*argv) bits_sample = atoi(*argv); else return -1;
|
||||
channels = 2;
|
||||
if (sample_rate < 1 || (bits_sample != 8 && bits_sample != 16 && bits_sample != 32)) {
|
||||
fprintf(stderr, "- <sr> <bs>\n");
|
||||
return -1;
|
||||
}
|
||||
pcm.sr = sample_rate;
|
||||
pcm.bps = bits_sample;
|
||||
pcm.nch = channels;
|
||||
option_pcmraw = 1;
|
||||
}
|
||||
else {
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
|
||||
fprintf(stderr, "error: open %s\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
wavloaded = 1;
|
||||
|
@ -986,9 +1086,31 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
if (!wavloaded) fp = stdin;
|
||||
|
||||
// ecc2-soft_decision accepts also 2-error words,
|
||||
// so the probability for 3 errors is high and will
|
||||
// produce wrong codewords. hence ecc2 is not recommended
|
||||
// for reliable frame decoding.
|
||||
//
|
||||
if ( option_dist || option_json ) option_ecc = 1;
|
||||
|
||||
|
||||
if (option_ecc)
|
||||
{
|
||||
ui8_t nib, msg[4], code[8];
|
||||
for (nib = 0; nib < 16; nib++) {
|
||||
nib4bits(nib, msg);
|
||||
gencode(msg, code);
|
||||
for (k = 0; k < 8; k++) codewords[nib][k] = code[k];
|
||||
}
|
||||
}
|
||||
|
||||
// init gpx
|
||||
strcpy(gpx.frame_bits, dfm_header); //, sizeof(dfm_header);
|
||||
//strcpy(gpx.frame_bits, dfm_header); //, sizeof(dfm_header);
|
||||
for (k = 0; k < strlen(dfm_header); k++) {
|
||||
gpx.frame[k].hb = dfm_header[k] & 1;
|
||||
gpx.frame[k].sb = 2*gpx.frame[k].hb - 1;
|
||||
}
|
||||
|
||||
for (k = 0; k < 9; k++) gpx.pck[k].ec = -1; // init ecc-status
|
||||
|
||||
gpx.option.inv = option_inv;
|
||||
|
@ -1005,14 +1127,23 @@ int main(int argc, char **argv) {
|
|||
|
||||
|
||||
if (!option_bin) {
|
||||
//if (option_iq) sel_wavch = 0;
|
||||
pcm.sel_ch = sel_wavch;
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
|
||||
if (option_iq == 0 && option_pcmraw) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
fprintf(stderr, "error: raw data not IQ\n");
|
||||
return -1;
|
||||
}
|
||||
if (option_iq) sel_wavch = 0;
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
if (option_pcmraw == 0) {
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// dfm: BT=1?, h=2.4?
|
||||
symlen = 2;
|
||||
|
@ -1068,89 +1199,96 @@ int main(int argc, char **argv) {
|
|||
bitofs += shift;
|
||||
|
||||
|
||||
while ( 1 )
|
||||
while ( 1 )
|
||||
{
|
||||
if (option_bin) { // aka find_binrawhead()
|
||||
header_found = find_binhead(fp, &hdb, &_mv); // symbols or bits?
|
||||
hdrcnt += nfrms;
|
||||
}
|
||||
else { // FM-audio:
|
||||
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
|
||||
_mv = dsp.mv;
|
||||
}
|
||||
if (header_found == EOF) break;
|
||||
|
||||
// mv == correlation score
|
||||
if (_mv *(0.5-gpx.option.inv) < 0) {
|
||||
if (gpx.option.aut == 0) header_found = 0;
|
||||
else gpx.option.inv ^= 0x1;
|
||||
}
|
||||
|
||||
if (header_found)
|
||||
{
|
||||
if (option_bin) { // aka find_binrawhead()
|
||||
header_found = find_binhead(fp, &hdb, &_mv); // symbols or bits?
|
||||
hdrcnt += nfrms;
|
||||
}
|
||||
else { // FM-audio:
|
||||
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
|
||||
_mv = dsp.mv;
|
||||
}
|
||||
if (header_found == EOF) break;
|
||||
bitpos = 0;
|
||||
pos = headerlen;
|
||||
pos /= 2;
|
||||
|
||||
// mv == correlation score
|
||||
if (_mv *(0.5-gpx.option.inv) < 0) {
|
||||
if (gpx.option.aut == 0) header_found = 0;
|
||||
else gpx.option.inv ^= 0x1;
|
||||
}
|
||||
//if (fabs(mv) > 0.85) nfrms = 8; else nfrms = 4; // test OK/KO/NO count
|
||||
|
||||
if (header_found)
|
||||
{
|
||||
bitpos = 0;
|
||||
pos = headerlen;
|
||||
pos /= 2;
|
||||
|
||||
//if (fabs(mv) > 0.85) nfrms = 8; else nfrms = 4; // test OK/KO/NO count
|
||||
|
||||
frm = 0;
|
||||
while ( frm < nfrms ) { // nfrms=1,2,4,8
|
||||
frm = 0;
|
||||
while ( frm < nfrms ) { // nfrms=1,2,4,8
|
||||
if (option_bin) {
|
||||
gpx._frmcnt = hdrcnt + frm;
|
||||
}
|
||||
else {
|
||||
gpx._frmcnt = dsp.mv_pos/(2.0*dsp.sps*BITFRAME_LEN) + frm;
|
||||
}
|
||||
while ( pos < BITFRAME_LEN )
|
||||
{
|
||||
if (option_bin) {
|
||||
gpx._frmcnt = hdrcnt + frm;
|
||||
// symbols or bits?
|
||||
// manchester1 1->10,0->01: 1.bit (DFM-06)
|
||||
// manchester2 0->10,1->01: 2.bit (DFM-09)
|
||||
bitQ = fgetc(fp);
|
||||
if (bitQ != EOF) {
|
||||
hsbit.hb = bitQ & 0x1;
|
||||
bitQ = fgetc(fp); // check: rbit0^rbit1=1 (Manchester)
|
||||
if (bitQ != EOF) hsbit.hb = bitQ & 0x1; // 2.bit (DFM-09)
|
||||
hsbit.sb = 2*hsbit.hb - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gpx._frmcnt = dsp.mv_pos/(2.0*dsp.sps*BITFRAME_LEN) + frm;
|
||||
}
|
||||
while ( pos < BITFRAME_LEN )
|
||||
{
|
||||
if (option_bin) {
|
||||
// symbols or bits?
|
||||
// manchester1 1->10,0->01: 1.bit (DFM-06)
|
||||
// manchester2 0->10,1->01: 2.bit (DFM-09)
|
||||
bitQ = fgetc(fp);
|
||||
if (bitQ != EOF) {
|
||||
bit = bitQ & 0x1;
|
||||
bitQ = fgetc(fp); // check: rbit0^rbit1=1 (Manchester)
|
||||
if (bitQ != EOF) bit = bitQ & 0x1; // 2.bit (DFM-09)
|
||||
}
|
||||
if (option_iq >= 2) {
|
||||
float bl = -1;
|
||||
if (option_iq > 2) bl = 4.0;
|
||||
bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, bl, 0);
|
||||
}
|
||||
else {
|
||||
if (option_iq >= 2) {
|
||||
float bl = -1;
|
||||
if (option_iq > 2) bl = 4.0;
|
||||
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, 0);
|
||||
}
|
||||
else {
|
||||
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, spike);
|
||||
}
|
||||
bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, -1, spike);
|
||||
}
|
||||
if ( bitQ == EOF ) { frm = nfrms; break; } // liest 2x EOF
|
||||
// optional:
|
||||
// normalize soft bit s_j by
|
||||
// rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1]
|
||||
|
||||
if (gpx.option.inv) bit ^= 1;
|
||||
|
||||
gpx.frame_bits[pos] = 0x30 + bit;
|
||||
pos++;
|
||||
bitpos += 1;
|
||||
}
|
||||
gpx.frame_bits[pos] = '\0';
|
||||
if ( bitQ == EOF ) { frm = nfrms; break; } // liest 2x EOF
|
||||
|
||||
ret = print_frame(&gpx);
|
||||
if (pos < BITFRAME_LEN) break;
|
||||
pos = 0;
|
||||
frm += 1;
|
||||
//if (ret < 0) frms += 1;
|
||||
if (gpx.option.inv) {
|
||||
hsbit.hb ^= 1;
|
||||
hsbit.sb = -hsbit.sb;
|
||||
}
|
||||
|
||||
gpx.frame[pos] = hsbit;
|
||||
pos++;
|
||||
bitpos += 1;
|
||||
}
|
||||
|
||||
ret = print_frame(&gpx);
|
||||
if (pos < BITFRAME_LEN) break;
|
||||
pos = 0;
|
||||
frm += 1;
|
||||
//if (ret < 0) frms += 1;
|
||||
}
|
||||
|
||||
header_found = 0;
|
||||
pos = headerlen;
|
||||
}
|
||||
|
||||
if (!option_bin) free_buffers(&dsp);
|
||||
else {
|
||||
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
|
||||
}
|
||||
header_found = 0;
|
||||
pos = headerlen;
|
||||
}
|
||||
|
||||
if (!option_bin) free_buffers(&dsp);
|
||||
else {
|
||||
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
|
||||
}
|
||||
|
||||
|
||||
fclose(fp);
|
||||
|
|
|
@ -477,7 +477,7 @@ static int get_GPStime(gpx_t *gpx, int crc_err) {
|
|||
gpstow_start = gpstime; // time elapsed since start-up?
|
||||
if (gpx->week > 0 && gpstime/1000.0 < time_elapsed_sec) gpx->week += 1;
|
||||
}
|
||||
gpx->gpstow = gpstime;
|
||||
gpx->gpstow = gpstime; // tow/ms
|
||||
|
||||
ms = gpstime % 1000;
|
||||
gpstime /= 1000;
|
||||
|
@ -517,6 +517,7 @@ static int get_GPStime_X(gpx_t *gpx) {
|
|||
}
|
||||
|
||||
gpx->gpstowX = *f64;
|
||||
gpx->gpstow = (ui32_t)(gpx->gpstowX*1e3); // tow/ms
|
||||
tow_u4 = (ui32_t)gpx->gpstowX;
|
||||
gpstime = tow_u4;
|
||||
gpx->gpssec = tow_u4;
|
||||
|
@ -737,11 +738,13 @@ static void print_frame(gpx_t *gpx, int crc_err, int len) {
|
|||
// UTC oder GPS?
|
||||
char sntyp[] = "LMS6-";
|
||||
if (gpx->typ == 10) sntyp[3] = 'X';
|
||||
printf("{ \"frame\": %d, \"id\": \"%s%d\", \"datetime\": \"", gpx->frnr, sntyp, gpx->sn );
|
||||
printf("{ \"type\": \"%s\"", "LMS6");
|
||||
printf(", \"frame\": %d, \"id\": \"%s%d\", \"datetime\": \"", gpx->frnr, sntyp, gpx->sn );
|
||||
//if (gpx->week > 0) printf("%04d-%02d-%02dT", gpx->jahr, gpx->monat, gpx->tag );
|
||||
printf("%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV );
|
||||
printf(", \"gpstow\": %d", gpx->gpstow );
|
||||
printf(", \"subtype\": \"%c\"", sntyp[3]);
|
||||
printf(" }\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -927,6 +930,7 @@ int main(int argc, char **argv) {
|
|||
int option_iq = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_pcmraw = 0;
|
||||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int gpsweek = 0;
|
||||
|
@ -1058,10 +1062,26 @@ int main(int argc, char **argv) {
|
|||
gpx->option.ecc = 1;
|
||||
gpx->option.vit = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
if (*argv) sample_rate = atoi(*argv); else return -1;
|
||||
++argv;
|
||||
if (*argv) bits_sample = atoi(*argv); else return -1;
|
||||
channels = 2;
|
||||
if (sample_rate < 1 || (bits_sample != 8 && bits_sample != 16 && bits_sample != 32)) {
|
||||
fprintf(stderr, "- <sr> <bs>\n");
|
||||
return -1;
|
||||
}
|
||||
pcm.sr = sample_rate;
|
||||
pcm.bps = bits_sample;
|
||||
pcm.nch = channels;
|
||||
option_pcmraw = 1;
|
||||
}
|
||||
else {
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
|
||||
fprintf(stderr, "error: open %s\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
wavloaded = 1;
|
||||
|
@ -1085,14 +1105,21 @@ int main(int argc, char **argv) {
|
|||
|
||||
gpx->week = gpsweek;
|
||||
|
||||
if (option_iq == 0 && option_pcmraw) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: raw data not IQ\n");
|
||||
return -1;
|
||||
}
|
||||
if (option_iq) sel_wavch = 0;
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
if (option_pcmraw == 0) {
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
symlen = 1;
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -790,8 +790,8 @@ static int print_pos(gpx_t *gpx, int csOK) {
|
|||
sn_id[15] = '\0';
|
||||
for (j = 0; sn_id[j]; j++) { if (sn_id[j] == ' ') sn_id[j] = '-'; }
|
||||
|
||||
fprintf(stdout, "{ ");
|
||||
fprintf(stdout, "\"frame\": %lu ,", (unsigned long)(sec_gps0+0.5));
|
||||
fprintf(stdout, "{ \"type\": \"%s\"", "M10");
|
||||
fprintf(stdout, ", \"frame\": %lu ,", (unsigned long)(sec_gps0+0.5));
|
||||
fprintf(stdout, "\"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d",
|
||||
sn_id, utc_jahr, utc_monat, utc_tag, utc_std, utc_min, utc_sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV);
|
||||
// APRS id, 9 characters
|
||||
|
@ -896,6 +896,7 @@ int main(int argc, char **argv) {
|
|||
int option_iq = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_pcmraw = 0;
|
||||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int spike = 0;
|
||||
|
@ -1001,10 +1002,26 @@ int main(int argc, char **argv) {
|
|||
option_min = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--json") == 0) { gpx.option.jsn = 1; }
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
if (*argv) sample_rate = atoi(*argv); else return -1;
|
||||
++argv;
|
||||
if (*argv) bits_sample = atoi(*argv); else return -1;
|
||||
channels = 2;
|
||||
if (sample_rate < 1 || (bits_sample != 8 && bits_sample != 16 && bits_sample != 32)) {
|
||||
fprintf(stderr, "- <sr> <bs>\n");
|
||||
return -1;
|
||||
}
|
||||
pcm.sr = sample_rate;
|
||||
pcm.bps = bits_sample;
|
||||
pcm.nch = channels;
|
||||
option_pcmraw = 1;
|
||||
}
|
||||
else {
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
|
||||
fprintf(stderr, "error: open %s\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
wavloaded = 1;
|
||||
|
@ -1023,13 +1040,22 @@ int main(int argc, char **argv) {
|
|||
|
||||
// init gpx
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
if (option_iq == 0 && option_pcmraw) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
fprintf(stderr, "error: raw data not IQ\n");
|
||||
return -1;
|
||||
}
|
||||
if (option_iq) sel_wavch = 0;
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
if (option_pcmraw == 0) {
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// m10: BT>1?, h=1.2 ?
|
||||
symlen = 2;
|
||||
|
|
|
@ -212,6 +212,7 @@ int main(int argc, char **argv) {
|
|||
int option_iq = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_pcmraw = 0;
|
||||
int sel_wavch = 0;
|
||||
int wavloaded = 0;
|
||||
|
||||
|
@ -307,6 +308,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
else return -1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left)
|
||||
else if ( (strcmp(*argv, "--ths") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
|
@ -345,12 +347,28 @@ int main(int argc, char **argv) {
|
|||
option_jsn = 1;
|
||||
option_ecc = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
if (*argv) sample_rate = atoi(*argv); else return -1;
|
||||
++argv;
|
||||
if (*argv) bits_sample = atoi(*argv); else return -1;
|
||||
channels = 2;
|
||||
if (sample_rate < 1 || (bits_sample != 8 && bits_sample != 16 && bits_sample != 32)) {
|
||||
fprintf(stderr, "- <sr> <bs>\n");
|
||||
return -1;
|
||||
}
|
||||
pcm.sr = sample_rate;
|
||||
pcm.bps = bits_sample;
|
||||
pcm.nch = channels;
|
||||
option_pcmraw = 1;
|
||||
}
|
||||
else {
|
||||
if (option1 == 1 && option2 == 1) goto help_out;
|
||||
if (!option_raw && option1 == 0 && option2 == 0) option2 = 1;
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
|
||||
fprintf(stderr, "error: open %s\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
wavloaded = 1;
|
||||
|
@ -360,13 +378,22 @@ int main(int argc, char **argv) {
|
|||
if (!wavloaded) fp = stdin;
|
||||
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
if (option_iq == 0 && option_pcmraw) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
fprintf(stderr, "error: raw data not IQ\n");
|
||||
return -1;
|
||||
}
|
||||
if (option_iq) sel_wavch = 0;
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
if (option_pcmraw == 0) {
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
symlen = 1;
|
||||
|
||||
|
@ -693,7 +720,8 @@ int main(int argc, char **argv) {
|
|||
if (gpx.sn > 0 && gpx.sn < 1e9) {
|
||||
sprintf(id_str, "%.0f", gpx.sn);
|
||||
}
|
||||
printf("{ \"frame\": %d, \"id\": \"IMS100-%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f }\n",
|
||||
printf("{ \"type\": \"%s\"", "IMS100");
|
||||
printf(", \"frame\": %d, \"id\": \"IMS100-%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f }\n",
|
||||
gpx.frnr, id_str, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD );
|
||||
printf("\n");
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* rs41
|
||||
* sync header: correlation/matched filter
|
||||
* files: rs41mod.c bch_ecc_mod.c demod_mod.c demod_mod.h
|
||||
* files: rs41mod.c bch_ecc_mod.c bch_ecc_mod.h demod_mod.c demod_mod.h
|
||||
* compile, either (a) or (b):
|
||||
* (a)
|
||||
* gcc -c demod_mod.c
|
||||
|
@ -1327,7 +1327,8 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
// Print out telemetry data as JSON
|
||||
if ((!err && !err1 && !err3) || (!err && encrypted)) { // frame-nb/id && gps-time && gps-position (crc-)ok; 3 CRCs, RS not needed
|
||||
// eigentlich GPS, d.h. UTC = GPS - 18sec (ab 1.1.2017)
|
||||
fprintf(stdout, "{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d, \"batt\": %.2f",
|
||||
fprintf(stdout, "{ \"type\": \"%s\"", "RS41");
|
||||
fprintf(stdout, ", \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d, \"batt\": %.2f",
|
||||
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV, gpx->conf_cd, gpx->batt );
|
||||
if (gpx->option.ptu && !err0 && gpx->T > -273.0) {
|
||||
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
|
||||
|
@ -1537,6 +1538,7 @@ int main(int argc, char *argv[]) {
|
|||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_bin = 0;
|
||||
int option_pcmraw = 0;
|
||||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int rawhex = 0, xorhex = 0;
|
||||
|
@ -1653,10 +1655,26 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
else if (strcmp(*argv, "--rawhex") == 0) { rawhex = 2; } // raw hex input
|
||||
else if (strcmp(*argv, "--xorhex") == 0) { rawhex = 2; xorhex = 1; } // raw xor input
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
if (*argv) sample_rate = atoi(*argv); else return -1;
|
||||
++argv;
|
||||
if (*argv) bits_sample = atoi(*argv); else return -1;
|
||||
channels = 2;
|
||||
if (sample_rate < 1 || (bits_sample != 8 && bits_sample != 16 && bits_sample != 32)) {
|
||||
fprintf(stderr, "- <sr> <bs>\n");
|
||||
return -1;
|
||||
}
|
||||
pcm.sr = sample_rate;
|
||||
pcm.bps = bits_sample;
|
||||
pcm.nch = channels;
|
||||
option_pcmraw = 1;
|
||||
}
|
||||
else {
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
|
||||
fprintf(stderr, "error: open %s\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
wavloaded = 1;
|
||||
|
@ -1680,14 +1698,21 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if (!option_bin) {
|
||||
|
||||
if (option_iq == 0 && option_pcmraw) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: raw data not IQ\n");
|
||||
return -1;
|
||||
}
|
||||
if (option_iq) sel_wavch = 0;
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
if (option_pcmraw == 0) {
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// rs41: BT=0.5, h=0.8,1.0 ?
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* rs92
|
||||
* sync header: correlation/matched filter
|
||||
* files: rs92mod.c nav_gps_vel.c bch_ecc_mod.c demod_mod.c demod_mod.h
|
||||
* files: rs92mod.c nav_gps_vel.c bch_ecc_mod.c bch_ecc_mod.h demod_mod.c demod_mod.h
|
||||
* compile:
|
||||
* (a)
|
||||
* gcc -c demod_mod.c
|
||||
|
@ -1177,7 +1177,9 @@ static int print_position(gpx_t *gpx, int ec) { // GPS-Hoehe ueber Ellipsoid
|
|||
// Print out telemetry data as JSON //even if we don't have a valid GPS lock
|
||||
if ((gpx->crc & (crc_FRAME | crc_GPS))==0 && (gpx->gps.almanac || gpx->gps.ephem)) //(!err1 && !err3)
|
||||
{ // eigentlich GPS, d.h. UTC = GPS - UTC_OFS (UTC_OFS=18sec ab 1.1.2017)
|
||||
fprintf(stdout, "\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, "{ \"type\": \"%s\"", "RS92");
|
||||
fprintf(stdout, ", \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vU);
|
||||
if ((gpx->crc & crc_AUX)==0 && (gpx->aux[0] != 0 || gpx->aux[1] != 0 || gpx->aux[2] != 0 || gpx->aux[3] != 0)) {
|
||||
fprintf(stdout, ", \"aux\": \"%04x%04x%04x%04x\"", gpx->aux[0], gpx->aux[1], gpx->aux[2], gpx->aux[3]);
|
||||
|
@ -1235,6 +1237,7 @@ int main(int argc, char *argv[]) {
|
|||
int option_iq = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_pcmraw = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int spike = 0;
|
||||
int fileloaded = 0;
|
||||
|
@ -1418,10 +1421,26 @@ int main(int argc, char *argv[]) {
|
|||
option_min = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--ngp") == 0) { gpx.option.ngp = 1; } // RS92-NGP, RS92-D: 1680 MHz
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
if (*argv) sample_rate = atoi(*argv); else return -1;
|
||||
++argv;
|
||||
if (*argv) bits_sample = atoi(*argv); else return -1;
|
||||
channels = 2;
|
||||
if (sample_rate < 1 || (bits_sample != 8 && bits_sample != 16 && bits_sample != 32)) {
|
||||
fprintf(stderr, "- <sr> <bs>\n");
|
||||
return -1;
|
||||
}
|
||||
pcm.sr = sample_rate;
|
||||
pcm.bps = bits_sample;
|
||||
pcm.nch = channels;
|
||||
option_pcmraw = 1;
|
||||
}
|
||||
else {
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
|
||||
fprintf(stderr, "error: open %s\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
fileloaded = 1;
|
||||
|
@ -1461,13 +1480,22 @@ int main(int argc, char *argv[]) {
|
|||
// init gpx
|
||||
memcpy(gpx.frame, rs92_header_bytes, sizeof(rs92_header_bytes)); // 6 header bytes
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
if (option_iq == 0 && option_pcmraw) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
fprintf(stderr, "error: raw data not IQ\n");
|
||||
return -1;
|
||||
}
|
||||
if (option_iq) sel_wavch = 0;
|
||||
|
||||
pcm.sel_ch = sel_wavch;
|
||||
if (option_pcmraw == 0) {
|
||||
k = read_wav_header(&pcm, fp);
|
||||
if ( k < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// rs92-sgp: BT=0.5, h=1.0 ?
|
||||
symlen = 2;
|
||||
|
|
|
@ -42,35 +42,35 @@ typedef struct {
|
|||
} RS_t;
|
||||
|
||||
|
||||
static GF_t GF256RS = { f : 0x11D, // RS-GF(2^8): X^8 + X^4 + X^3 + X^2 + 1 : 0x11D
|
||||
ord : 256, // 2^8
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF256RS = { .f = 0x11D, // RS-GF(2^8): X^8 + X^4 + X^3 + X^2 + 1 : 0x11D
|
||||
.ord = 256, // 2^8
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF256RSccsds = { f : 0x187, // RS-GF(2^8): X^8 + X^7 + X^2 + X + 1 : 0x187
|
||||
ord : 256, // 2^8
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF256RSccsds = { .f = 0x187, // RS-GF(2^8): X^8 + X^7 + X^2 + X + 1 : 0x187
|
||||
.ord = 256, // 2^8
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF64BCH = { f : 0x43, // BCH-GF(2^6): X^6 + X + 1 : 0x43
|
||||
ord : 64, // 2^6
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF64BCH = { .f = 0x43, // BCH-GF(2^6): X^6 + X + 1 : 0x43
|
||||
.ord = 64, // 2^6
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF16RS = { f : 0x13, // RS-GF(2^4): X^4 + X + 1 : 0x13
|
||||
ord : 16, // 2^4
|
||||
alpha: 0x02, // generator: alpha = X
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF16RS = { .f = 0x13, // RS-GF(2^4): X^4 + X + 1 : 0x13
|
||||
.ord = 16, // 2^4
|
||||
.alpha = 0x02, // generator: alpha = X
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
static GF_t GF256AES = { f : 0x11B, // AES-GF(2^8): X^8 + X^4 + X^3 + X + 1 : 0x11B
|
||||
ord : 256, // 2^8
|
||||
alpha: 0x03, // generator: alpha = X+1
|
||||
exp_a: {0},
|
||||
log_a: {0} };
|
||||
static GF_t GF256AES = { .f = 0x11B, // AES-GF(2^8): X^8 + X^4 + X^3 + X + 1 : 0x11B
|
||||
.ord = 256, // 2^8
|
||||
.alpha = 0x03, // generator: alpha = X+1
|
||||
.exp_a = {0},
|
||||
.log_a = {0} };
|
||||
|
||||
|
||||
static RS_t RS256 = { 255, 12, 24, 231, 0, 1, 1, {0}, {0} };
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
#include <complex.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.1415926535897932384626433832795)
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned char ui8_t;
|
||||
typedef unsigned short ui16_t;
|
||||
typedef unsigned int ui32_t;
|
||||
|
|
|
@ -560,6 +560,11 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) {
|
|||
gpx->status[1] = val/100.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gpx->status[0] = 0;
|
||||
gpx->status[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -668,8 +673,12 @@ static int print_gpx(gpx_t *gpx) {
|
|||
}
|
||||
|
||||
// Print JSON blob // valid sonde_ID?
|
||||
printf("{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
printf("{ \"type\": \"%s\"", "DFM");
|
||||
printf(", \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
gpx->frnr, json_sonde_id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->horiV, gpx->dir, gpx->vertV);
|
||||
if (gpx->ptu_out >= 0xA && gpx->status[0] > 0) { // DFM>=09(P): Battery (STM32)
|
||||
printf(", \"batt\": %.2f", gpx->status[0]);
|
||||
}
|
||||
if (gpx->ptu_out) { // get temperature
|
||||
float t = get_Temp(gpx); // ecc-valid temperature?
|
||||
if (t > -270.0) printf(", \"temp\": %.1f", t);
|
||||
|
|
|
@ -730,11 +730,13 @@ static int print_frame(gpx_t *gpx, int crc_err, int len) {
|
|||
// UTC oder GPS?
|
||||
char sntyp[] = "LMS6-";
|
||||
if (gpx->typ == 10) sntyp[3] = 'X';
|
||||
printf("{ \"frame\": %d, \"id\": \"%s%d\", \"datetime\": \"", gpx->frnr, sntyp, gpx->sn );
|
||||
printf("{ \"type\": \"%s\"", "LMS6");
|
||||
printf(", \"frame\": %d, \"id\": \"%s%d\", \"datetime\": \"", gpx->frnr, sntyp, gpx->sn );
|
||||
//if (gpx->week > 0) printf("%04d-%02d-%02dT", gpx->jahr, gpx->monat, gpx->tag );
|
||||
printf("%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV );
|
||||
printf(", \"gpstow\": %d", gpx->gpstow );
|
||||
printf(", \"subtype\": \"%c\"", sntyp[3]);
|
||||
printf(" }\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
|
|
@ -789,8 +789,8 @@ static int print_pos(gpx_t *gpx, int csOK) {
|
|||
sn_id[15] = '\0';
|
||||
for (j = 0; sn_id[j]; j++) { if (sn_id[j] == ' ') sn_id[j] = '-'; }
|
||||
|
||||
fprintf(stdout, "{ ");
|
||||
fprintf(stdout, "\"frame\": %lu ,", (unsigned long)(sec_gps0+0.5));
|
||||
fprintf(stdout, "{ \"type\": \"%s\"", "M10");
|
||||
fprintf(stdout, ", \"frame\": %lu ,", (unsigned long)(sec_gps0+0.5));
|
||||
fprintf(stdout, "\"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d",
|
||||
sn_id, utc_jahr, utc_monat, utc_tag, utc_std, utc_min, utc_sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV);
|
||||
// APRS id, 9 characters
|
||||
|
|
|
@ -1321,7 +1321,8 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
// Print out telemetry data as JSON
|
||||
if ((!err && !err1 && !err3) || (!err && encrypted)) { // frame-nb/id && gps-time && gps-position (crc-)ok; 3 CRCs, RS not needed
|
||||
// eigentlich GPS, d.h. UTC = GPS - 18sec (ab 1.1.2017)
|
||||
fprintf(stdout, "{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d, \"batt\": %.2f",
|
||||
fprintf(stdout, "{ \"type\": \"%s\"", "RS41");
|
||||
fprintf(stdout, ", \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d, \"batt\": %.2f",
|
||||
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV, gpx->conf_cd, gpx->batt );
|
||||
if (gpx->option.ptu && !err0 && gpx->T > -273.0) {
|
||||
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
|
||||
|
|
243
dfm/dfm06ptu.c
243
dfm/dfm06ptu.c
|
@ -322,6 +322,56 @@ int read_rawbit3(FILE *fp, int *bit) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
ui8_t hb;
|
||||
float sb;
|
||||
} hsbit_t;
|
||||
|
||||
int soft_read_rawbit2(FILE *fp, hsbit_t *shb) {
|
||||
int sample;
|
||||
int sum;
|
||||
ui8_t bit = 0;
|
||||
|
||||
sum = 0;
|
||||
|
||||
if (bitstart) {
|
||||
scount = 0; // eigentlich scount = 1
|
||||
bitgrenze = 0; // oder bitgrenze = -1
|
||||
bitstart = 0;
|
||||
}
|
||||
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
sample = read_signed_sample(fp);
|
||||
if (sample == EOF_INT) return EOF;
|
||||
//sample_count++; // in read_signed_sample()
|
||||
//par = (sample >= 0) ? 1 : -1; // 8bit: 0..127,128..255 (-128..-1,0..127)
|
||||
sum += sample;
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
sample = read_signed_sample(fp);
|
||||
if (sample == EOF_INT) return EOF;
|
||||
//sample_count++; // in read_signed_sample()
|
||||
//par = (sample >= 0) ? 1 : -1; // 8bit: 0..127,128..255 (-128..-1,0..127)
|
||||
sum -= sample;
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
|
||||
if (option_inv) sum = -sum; // sum=0 bleibt bit=1
|
||||
// jedoch sb und hb werden zusammen invertiert
|
||||
if (sum >= 0) bit = 1;
|
||||
else bit = 0;
|
||||
|
||||
shb->hb = bit;
|
||||
shb->sb = sum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
//#define BITS (2*8) // 16
|
||||
|
@ -341,6 +391,8 @@ int bufpos = -1;
|
|||
char frame_rawbits[RAWBITFRAME_LEN+8] = "01100101011001101010010110101010"; //->"0100010111001111";
|
||||
char frame_bits[BITFRAME_LEN+4];
|
||||
|
||||
hsbit_t frm[BITFRAME_LEN+4];
|
||||
|
||||
|
||||
void inc_bufpos() {
|
||||
bufpos = (bufpos+1) % HEADLEN;
|
||||
|
@ -417,6 +469,16 @@ void manchester1(char* frame_rawbits, char *frame_bits, int pos) {
|
|||
#define DAT2 (16+160) // 104 bit
|
||||
// frame: 280 bit
|
||||
|
||||
ui8_t G[8][4] = // Generator
|
||||
{{ 1, 0, 0, 0},
|
||||
{ 0, 1, 0, 0},
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 1},
|
||||
{ 0, 1, 1, 1},
|
||||
{ 1, 0, 1, 1},
|
||||
{ 1, 1, 0, 1},
|
||||
{ 1, 1, 1, 0}};
|
||||
|
||||
ui8_t H[4][8] = // Parity-Check
|
||||
{{ 0, 1, 1, 1, 1, 0, 0, 0},
|
||||
{ 1, 0, 1, 1, 0, 1, 0, 0},
|
||||
|
@ -432,6 +494,33 @@ ui8_t block_conf[ 7*S]; // 7*4=28
|
|||
ui8_t block_dat1[13*S]; // 13*4=52
|
||||
ui8_t block_dat2[13*S];
|
||||
|
||||
hsbit_t soft_hamming_conf[ 7*B]; // 7*8=56
|
||||
hsbit_t soft_hamming_dat1[13*B]; // 13*8=104
|
||||
hsbit_t soft_hamming_dat2[13*B];
|
||||
|
||||
ui8_t codewords[16][8];
|
||||
|
||||
int nib4bits(ui8_t nib, ui8_t *bits) { // big endian
|
||||
int j;
|
||||
|
||||
nib &= 0xF;
|
||||
for (j = 0; j < 4; j++) {
|
||||
bits[j] = (nib>>(3-j)) & 0x1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gencode(ui8_t msg[4], ui8_t code[8]) {
|
||||
int i, j; // Gm=c
|
||||
for (i = 0; i < 8; i++) {
|
||||
code[i] = 0;
|
||||
for (j = 0; j < 4; j++) {
|
||||
code[i] ^= G[i][j] & msg[j];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ui32_t bits2val(ui8_t *bits, int len) { // big endian
|
||||
int j;
|
||||
ui32_t val;
|
||||
|
@ -454,6 +543,15 @@ void deinterleave(char *str, int L, ui8_t *block) {
|
|||
}
|
||||
}
|
||||
|
||||
void soft_deinterleave(hsbit_t *str, int L, hsbit_t *block) {
|
||||
int i, j;
|
||||
for (j = 0; j < B; j++) { // L = 7, 13
|
||||
for (i = 0; i < L; i++) {
|
||||
block[B*i+j] = str[L*j+i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int check(ui8_t code[8]) {
|
||||
int i, j; // Bei Demodulierung durch Nulldurchgaenge, wenn durch Fehler ausser Takt,
|
||||
ui32_t synval = 0; // verschieben sich die bits. Fuer Hamming-Decode waere es besser,
|
||||
|
@ -494,6 +592,82 @@ int hamming(ui8_t *ham, int L, ui8_t *sym) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int soft_check(hsbit_t code[8]) {
|
||||
int i, j; // Bei Demodulierung durch Nulldurchgaenge, wenn durch Fehler ausser Takt,
|
||||
ui32_t synval = 0; // verschieben sich die bits. Fuer Hamming-Decode waere es besser,
|
||||
ui8_t syndrom[4]; // sync zu Beginn mit Header und dann Takt beibehalten fuer decision.
|
||||
int ret=0;
|
||||
|
||||
for (i = 0; i < 4; i++) { // S = 4
|
||||
syndrom[i] = 0;
|
||||
for (j = 0; j < 8; j++) { // B = 8
|
||||
syndrom[i] ^= H[i][j] & code[j].hb;
|
||||
}
|
||||
}
|
||||
synval = bits2val(syndrom, 4);
|
||||
if (synval) {
|
||||
ret = -1;
|
||||
for (j = 0; j < 8; j++) { // 1-bit-error
|
||||
if (synval == He[j]) { // reicht auf databits zu pruefen, d.h.
|
||||
ret = j+1; // (systematischer Code) He[0..3]
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else ret = 0; // d=0: valid codeword
|
||||
|
||||
if (ret > 0) code[ret-1].hb ^= 0x1; // d=1: 1-bit-error
|
||||
else if (ret < 0 && option_ecc == 2) { // d=2: 2-bit-error: soft decision
|
||||
int n;
|
||||
int count = 0;
|
||||
int maxn = -1;
|
||||
int d = 0;
|
||||
float sum = 0.0;
|
||||
float maxsum = 0.0;
|
||||
for (n = 0; n < 16; n++) {
|
||||
d = 0;
|
||||
for (i = 0; i < 8; i++) { // d(a,b) = sum_i a[i]^b[i]
|
||||
if (code[i].hb != codewords[n][i]) d++;
|
||||
}
|
||||
if (d == 2) { // dist=2
|
||||
count++;
|
||||
// sum softbits
|
||||
// correlation: - interleaving
|
||||
// + no pulse-shaping -> sum
|
||||
//
|
||||
sum = 0.0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
sum += (2*codewords[n][i]-1) * code[i].sb;
|
||||
}
|
||||
if (sum >= maxsum) {
|
||||
maxsum = sum;
|
||||
maxn = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (maxn >= 0) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (code[i].hb = codewords[maxn][i]);
|
||||
}
|
||||
//ret = 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int soft_hamming(hsbit_t *ham, int L, ui8_t *sym) {
|
||||
int i, j;
|
||||
int ret = 0; // L = 7, 13
|
||||
for (i = 0; i < L; i++) { // L * 2 nibble (data+parity)
|
||||
if (option_ecc) ret |= soft_check(ham+B*i);
|
||||
for (j = 0; j < S; j++) { // systematic: bits 0..S-1 data
|
||||
sym[S*i+j] = ham[B*i+j].hb;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char nib2chr(ui8_t nib) {
|
||||
char c = '_';
|
||||
if (nib < 0x10) {
|
||||
|
@ -998,13 +1172,27 @@ void print_frame() {
|
|||
manchester1(frame_rawbits, frame_bits, RAWBITFRAME_LEN);
|
||||
}
|
||||
|
||||
deinterleave(frame_bits+CONF, 7, hamming_conf);
|
||||
deinterleave(frame_bits+DAT1, 13, hamming_dat1);
|
||||
deinterleave(frame_bits+DAT2, 13, hamming_dat2);
|
||||
|
||||
ret0 = hamming(hamming_conf, 7, block_conf);
|
||||
ret1 = hamming(hamming_dat1, 13, block_dat1);
|
||||
ret2 = hamming(hamming_dat2, 13, block_dat2);
|
||||
if (option_ecc == 2) {
|
||||
soft_deinterleave(frm+CONF, 7, soft_hamming_conf);
|
||||
soft_deinterleave(frm+DAT1, 13, soft_hamming_dat1);
|
||||
soft_deinterleave(frm+DAT2, 13, soft_hamming_dat2);
|
||||
|
||||
ret0 = soft_hamming(soft_hamming_conf, 7, block_conf);
|
||||
ret1 = soft_hamming(soft_hamming_dat1, 13, block_dat1);
|
||||
ret2 = soft_hamming(soft_hamming_dat2, 13, block_dat2);
|
||||
}
|
||||
else {
|
||||
deinterleave(frame_bits+CONF, 7, hamming_conf);
|
||||
deinterleave(frame_bits+DAT1, 13, hamming_dat1);
|
||||
deinterleave(frame_bits+DAT2, 13, hamming_dat2);
|
||||
|
||||
ret0 = hamming(hamming_conf, 7, block_conf);
|
||||
ret1 = hamming(hamming_dat1, 13, block_dat1);
|
||||
ret2 = hamming(hamming_dat2, 13, block_dat2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (option_raw == 1) {
|
||||
|
||||
|
@ -1042,14 +1230,14 @@ void print_frame() {
|
|||
}
|
||||
else if (option_ecc) {
|
||||
|
||||
if (ret0 == 0 || ret0 > 0) {
|
||||
if (ret0 == 0 || ret0 > 0 || option_ecc == 2) {
|
||||
conf_out(block_conf);
|
||||
}
|
||||
if (ret1 == 0 || ret1 > 0) {
|
||||
if (ret1 == 0 || ret1 > 0 || option_ecc == 2) {
|
||||
frid = dat_out(block_dat1);
|
||||
if (frid == 8) print_gpx();
|
||||
}
|
||||
if (ret2 == 0 || ret2 > 0) {
|
||||
if (ret2 == 0 || ret2 > 0 || option_ecc == 2) {
|
||||
frid = dat_out(block_dat2);
|
||||
if (frid == 8) print_gpx();
|
||||
}
|
||||
|
@ -1120,9 +1308,8 @@ int main(int argc, char **argv) {
|
|||
else if (strcmp(*argv, "-b" ) == 0) { option_b = 1; }
|
||||
else if (strcmp(*argv, "-b2") == 0) { option_b = 2; }
|
||||
else if (strcmp(*argv, "-b3") == 0) { option_b = 3; }
|
||||
else if ( (strcmp(*argv, "--ecc") == 0) ) {
|
||||
option_ecc = 1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--ecc" ) == 0) ) { option_ecc = 1; }
|
||||
else if ( (strcmp(*argv, "--ecc2") == 0) ) { option_ecc = 2; }
|
||||
else if ( (strcmp(*argv, "--ptu") == 0) ) {
|
||||
option_ptu = 1;
|
||||
//ptu_out = 1; // force ptu (non PS-15)
|
||||
|
@ -1140,6 +1327,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
if (!wavloaded) fp = stdin;
|
||||
|
||||
if (option_ecc == 2) option_b = 2;
|
||||
|
||||
i = read_wav_header(fp);
|
||||
if (i) {
|
||||
|
@ -1155,6 +1343,16 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
|
||||
if (option_ecc == 2) {
|
||||
ui8_t nib, msg[4], code[8];
|
||||
for (nib = 0; nib < 16; nib++) {
|
||||
nib4bits(nib, msg);
|
||||
gencode(msg, code);
|
||||
for (i = 0; i < 8; i++) codewords[nib][i] = code[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
for (j = 0; j < 13; j++) dat_str[i][j] = ' ';
|
||||
}
|
||||
|
@ -1224,9 +1422,26 @@ int main(int argc, char **argv) {
|
|||
manchester1(frame_rawbits, frame_bits, pos);
|
||||
pos /= 2;
|
||||
|
||||
if (option_ecc == 2) {
|
||||
for (i = 0; i < pos; i++) {
|
||||
frm[i].hb = frame_bits[i] % 1;
|
||||
frm[i].sb = 0.0; // (ecc2) bit=1: sb>0 , bit=0: sb<0
|
||||
}
|
||||
}
|
||||
|
||||
while ( pos < BITFRAME_LEN ) {
|
||||
if (option_b==2) { if (read_rawbit2(fp, &bit) == EOF) break; }
|
||||
else { if (read_rawbit3(fp, &bit) == EOF) break; }
|
||||
if (option_b == 2) {
|
||||
if (option_ecc == 2) {
|
||||
if (soft_read_rawbit2(fp, frm+pos) == EOF) break;
|
||||
bit = frm[pos].hb;
|
||||
}
|
||||
else {
|
||||
if (read_rawbit2(fp, &bit) == EOF) break;
|
||||
}
|
||||
}
|
||||
else { // option_b==3
|
||||
if (read_rawbit3(fp, &bit) == EOF) break;
|
||||
}
|
||||
frame_bits[pos] = 0x30 + bit;
|
||||
pos++;
|
||||
}
|
||||
|
|
19
ecc/ecc.txt
19
ecc/ecc.txt
|
@ -5,14 +5,21 @@ Einige Radiosonden senden frames mit Codewoertern, die eine Fehlerkorrektur ermo
|
|||
|
||||
Graw
|
||||
====
|
||||
BCH/Hamming code (N, N-R) = (2^m - 1, N-m), d.h. R=mt mit t=1,
|
||||
Hammingcode (N, N-R) = (2^m - 1, N-m), d.h. R=mt mit t=1,
|
||||
korrigiert t=1 Fehler pro Codewort der Laenge N,
|
||||
die Codewoerter haben den Abstand d=3 (bei 2 Fehlern
|
||||
wird falsch dekodiert).
|
||||
Fuer die Sonden DFM-06/09 ist m=3, d.h. Hamming (7, 4),
|
||||
jedoch mit einem Paritaetsbit zu (8, 4) erweitert.
|
||||
Der erweiterte Hammingcode (8, 4) kann zudem 2 Fehler
|
||||
die Codewoerter haben den (min.) Abstand d=3
|
||||
(bei 2 Fehlern wird zum Nachbarcodewort falsch dekodiert).
|
||||
|
||||
Fuer die Sonden DFM-06/09 ist m=3, d.h. Hamming(7,4),
|
||||
jedoch mit einem Paritaetsbit zu (8,4) erweitert.
|
||||
|
||||
Der erweiterte Hammingcode (8,4) kann zudem 2 Fehler
|
||||
als nicht-korrigierbar erkennen (wird nicht falsch decodiert).
|
||||
Zu einem Wort mit 2 Fehlern gibt es 4 Codewoerter mit Abstand 2.
|
||||
Von diesen kann das Codewort, das am besten passt, ausgewaehlt
|
||||
werden (soft decision). Allerdings steigt die Wahrscheinlichkeit,
|
||||
dass neben 2 Fehlern auch Woerter mit 3 Fehlern vorkommen, wobei
|
||||
diese dann falsch decodiert werden.
|
||||
|
||||
|
||||
Meisei
|
||||
|
|
Plik binarny nie jest wyświetlany.
|
@ -427,7 +427,8 @@ int print_frame(int len) {
|
|||
if (option_json) {
|
||||
if (gpx.gps_valid && gpx.ptu_valid) // frameNb part of PTU-pck
|
||||
{
|
||||
fprintf(stdout, "{ \"frame\": %d, \"id\": \"iMet\", \"datetime\": \"%02d:%02d:%02dZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %d, \"sats\": %d, \"temp\": %.2f, \"humidity\": %.2f, \"pressure\": %.2f, \"batt\": %.1f }\n",
|
||||
fprintf(stdout, "{ \"type\": \"%s\"", "IMET");
|
||||
fprintf(stdout, ", \"frame\": %d, \"id\": \"iMet\", \"datetime\": \"%02d:%02d:%02dZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %d, \"sats\": %d, \"temp\": %.2f, \"humidity\": %.2f, \"pressure\": %.2f, \"batt\": %.1f }\n",
|
||||
gpx.frame, gpx.hour, gpx.min, gpx.sec, gpx.lat, gpx.lon, gpx.alt, gpx.sats, gpx.temp, gpx.humidity, gpx.pressure, gpx.batt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
/* big endian forest
|
||||
*
|
||||
* gcc mXX_20180919.c -lm
|
||||
* 2018-09-19 Ury?
|
||||
*
|
||||
* 2018-09-19 Ury: (len=0x43)
|
||||
* 2019-11-06 Ury: (len=0x45) ./a.out -b -c -v --br 9600 new_rs_48k.wav
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -67,7 +69,7 @@ void Gps2Date(long GpsWeek, long GpsSeconds, int *Year, int *Month, int *Day) {
|
|||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define BAUD_RATE 9616 //2*4800
|
||||
#define BAUD_RATE 9600 //9616 //2*4800
|
||||
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
float samples_per_bit = 0;
|
||||
|
@ -295,6 +297,7 @@ dduudduudduudduu duduudduuduudduu ddududuudduduudd uduuddududududud uudduduuddu
|
|||
//"011101101001111100100000"; // M10: 76 9F 20 , aux-data?
|
||||
//"011001000100100100001001"; // M10-dop: 64 49 09
|
||||
//"011001001010111100000010"; // M10gtop: 64 AF 02
|
||||
// M20?: 45 20
|
||||
char header[] = "10011001100110010100110010011001";
|
||||
|
||||
#define FRAME_LEN (0x43+1) //(100+1) // 0x64+1
|
||||
|
@ -504,7 +507,8 @@ int get_GPSweek() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
char weekday[7][3] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
|
||||
//char weekday[7][3] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
|
||||
char weekday[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||
|
||||
int get_GPStime() {
|
||||
int i;
|
||||
|
@ -591,6 +595,33 @@ int get_GPSvel() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static float get_Tntc0(ui8_t *frame, int csOK) {
|
||||
// SMD ntc
|
||||
float Rs = 22.1e3; // P5.6=Vcc
|
||||
float R25 = 2.2e3;// 0.119e3; //2.2e3;
|
||||
float b = 3650.0; // B/Kelvin
|
||||
float T25 = 25.0 + 273.15; // T0=25C, R0=R25=5k
|
||||
// -> Steinhart–Hart coefficients (polyfit):
|
||||
float p0 = 4.42606809e-03,
|
||||
p1 = -6.58184309e-04,
|
||||
p2 = 8.95735557e-05,
|
||||
p3 = -2.84347503e-06;
|
||||
float T = 0.0; // T/Kelvin
|
||||
ui16_t ADC_ntc0; // M10: ADC12 P6.4(A4)
|
||||
float x, R;
|
||||
if (csOK)
|
||||
{
|
||||
ADC_ntc0 = (frame[0x07] << 8) | frame[0x06]; // M10: 0x40,0x3F
|
||||
x = (4095.0 - ADC_ntc0)/ADC_ntc0; // (Vcc-Vout)/Vout
|
||||
R = Rs / x;
|
||||
if (R > 0) T = 1/(1/T25 + 1/b * log(R/R25));
|
||||
//if (R > 0) T = 1/( p0 + p1*log(R) + p2*log(R)*log(R) + p3*log(R)*log(R)*log(R) );
|
||||
}
|
||||
return T - 273.15;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/*
|
||||
g : F^n -> F^16 // checksum, linear
|
||||
|
@ -667,6 +698,9 @@ int print_pos(int csOK) {
|
|||
|
||||
Gps2Date(datum.week, datum.gpssec, &datum.jahr, &datum.monat, &datum.tag);
|
||||
|
||||
// counter
|
||||
fprintf(stdout, "[%3d]", frame_bytes[0x15]);
|
||||
|
||||
if (option_color) {
|
||||
fprintf(stdout, col_TXT);
|
||||
|
||||
|
@ -686,6 +720,12 @@ int print_pos(int csOK) {
|
|||
if (csOK) fprintf(stdout, " "col_CSok"[OK]"col_TXT);
|
||||
else fprintf(stdout, " "col_CSno"[NO]"col_TXT);
|
||||
}
|
||||
|
||||
if (option_verbose >= 2) {
|
||||
float t0 = get_Tntc0(frame_bytes, csOK);
|
||||
if (t0 > -270.0) fprintf(stdout, " (T0:%.1fC)", t0);
|
||||
}
|
||||
|
||||
fprintf(stdout, ANSI_COLOR_RESET"");
|
||||
}
|
||||
else {
|
||||
|
@ -704,9 +744,15 @@ int print_pos(int csOK) {
|
|||
fprintf(stdout, " # ");
|
||||
if (csOK) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]");
|
||||
}
|
||||
|
||||
if (option_verbose >= 2) {
|
||||
float t0 = get_Tntc0(frame_bytes, csOK);
|
||||
if (t0 > -270.0) fprintf(stdout, " (T0:%.1fC)", t0);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -728,8 +774,8 @@ void print_frame(int pos) {
|
|||
if (auxlen < 0 || auxlen > AUX_LEN) auxlen = 0;
|
||||
}
|
||||
|
||||
cs1 = (frame_bytes[pos_Check] << 8) | frame_bytes[pos_Check+1];
|
||||
cs2 = checkM10(frame_bytes, pos_Check);
|
||||
cs1 = (frame_bytes[pos_Check+auxlen] << 8) | frame_bytes[pos_Check+auxlen+1];
|
||||
cs2 = checkM10(frame_bytes, pos_Check+auxlen);
|
||||
|
||||
if (option_raw) {
|
||||
|
||||
|
@ -745,7 +791,7 @@ void print_frame(int pos) {
|
|||
if ((i >= pos_GPSvE) && (i < pos_GPSvE+2)) fprintf(stdout, col_GPSvel);
|
||||
if ((i >= pos_GPSvN) && (i < pos_GPSvN+2)) fprintf(stdout, col_GPSvel);
|
||||
if ((i >= pos_GPSvU) && (i < pos_GPSvU+2)) fprintf(stdout, col_GPSvel);
|
||||
if ((i >= pos_Check) && (i < pos_Check+2)) fprintf(stdout, col_Check);
|
||||
if ((i >= pos_Check+auxlen) && (i < pos_Check+auxlen+2)) fprintf(stdout, col_Check);
|
||||
fprintf(stdout, "%02x", byte);
|
||||
fprintf(stdout, col_FRTXT);
|
||||
}
|
||||
|
@ -784,6 +830,7 @@ int main(int argc, char **argv) {
|
|||
int bit, bit0;
|
||||
int pos;
|
||||
int header_found = 0;
|
||||
float baudrate = -1;
|
||||
|
||||
|
||||
#ifdef CYGWIN
|
||||
|
@ -820,6 +867,14 @@ int main(int argc, char **argv) {
|
|||
else if (strcmp(*argv, "-b" ) == 0) { option_b = 1; }
|
||||
else if (strcmp(*argv, "-b2") == 0) { option_b = 2; }
|
||||
else if (strcmp(*argv, "--ch2") == 0) { wav_channel = 1; } // right channel (default: 0=left)
|
||||
else if ( (strcmp(*argv, "--br") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
baudrate = atof(*argv);
|
||||
if (baudrate < 9000 || baudrate > 10000) baudrate = BAUD_RATE; // default: 9615
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
else {
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
|
@ -838,6 +893,10 @@ int main(int argc, char **argv) {
|
|||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
if (baudrate > 0) {
|
||||
samples_per_bit = sample_rate/baudrate;
|
||||
fprintf(stderr, "sps corr: %.4f\n", samples_per_bit);
|
||||
}
|
||||
|
||||
|
||||
pos = FRAMESTART;
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
|
||||
/*
|
||||
* compile:
|
||||
* gcc dft_detect.c -lm -o dft_detect
|
||||
* speedup:
|
||||
* gcc -Ofast dft_detect.c -lm -o dft_detect
|
||||
*
|
||||
* author: zilog80
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <complex.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.1415926535897932384626433832795)
|
||||
#endif
|
||||
|
||||
typedef unsigned char ui8_t;
|
||||
typedef unsigned short ui16_t;
|
||||
|
@ -574,7 +586,7 @@ static int lowpass_init(float f, int taps, float **pws) {
|
|||
|
||||
h = (double*)calloc( taps+1, sizeof(double)); if (h == NULL) return -1;
|
||||
w = (double*)calloc( taps+1, sizeof(double)); if (w == NULL) return -1;
|
||||
ws = (float*)calloc( taps+1, sizeof(float)); if (ws == NULL) return -1;
|
||||
ws = (float*)calloc( 2*taps+1, sizeof(float)); if (ws == NULL) return -1;
|
||||
|
||||
for (n = 0; n < taps; n++) {
|
||||
w[n] = 7938/18608.0 - 9240/18608.0*cos(2*M_PI*n/(taps-1)) + 1430/18608.0*cos(4*M_PI*n/(taps-1)); // Blackmann
|
||||
|
@ -585,6 +597,9 @@ static int lowpass_init(float f, int taps, float **pws) {
|
|||
for (n = 0; n < taps; n++) {
|
||||
ws[n] /= norm; // 1-norm
|
||||
}
|
||||
|
||||
for (n = 0; n < taps; n++) ws[taps+n] = ws[n]; // duplicate/unwrap
|
||||
|
||||
*pws = ws;
|
||||
|
||||
free(h); h = NULL;
|
||||
|
@ -594,7 +609,7 @@ static int lowpass_init(float f, int taps, float **pws) {
|
|||
}
|
||||
|
||||
// struct { int taps; double *ws}
|
||||
static float complex lowpass(float complex buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
static float complex lowpass0(float complex buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
ui32_t n;
|
||||
double complex w = 0;
|
||||
for (n = 0; n < taps; n++) {
|
||||
|
@ -602,6 +617,16 @@ static float complex lowpass(float complex buffer[], ui32_t sample, ui32_t taps,
|
|||
}
|
||||
return (float complex)w;
|
||||
}
|
||||
static float complex lowpass(float complex buffer[], ui32_t sample, ui32_t taps, float *ws) {
|
||||
ui32_t n;
|
||||
ui32_t s = sample % taps;
|
||||
double complex w = 0;
|
||||
for (n = 0; n < taps; n++) {
|
||||
w += buffer[n]*ws[taps+s-n]; // ws[taps+s-n] = ws[(taps+sample-n)%taps]
|
||||
}
|
||||
return (float complex)w;
|
||||
// symmetry: ws[n] == ws[taps-1-n]
|
||||
}
|
||||
|
||||
|
||||
static int f32buf_sample(FILE *fp, int inv) {
|
||||
|
@ -1197,7 +1222,7 @@ int main(int argc, char **argv) {
|
|||
else {
|
||||
fp = fopen(*argv, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
|
||||
fprintf(stderr, "error: open %s\n", *argv);
|
||||
return -50;
|
||||
}
|
||||
wavloaded = 1;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#!/usr/bin/env perl
|
||||
## aprs-output provided by daniestevez
|
||||
## axudp extensions provided by dl9rdz
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use IO::Socket::INET;
|
||||
use Getopt::Long;
|
||||
|
||||
my $filename = undef;
|
||||
my $date = undef;
|
||||
|
@ -11,6 +13,9 @@ my $mycallsign;
|
|||
my $passcode;
|
||||
my $comment;
|
||||
|
||||
my $udp;
|
||||
GetOptions("u=s" => \$udp) or die "Error in command line arguments\n";
|
||||
|
||||
while (@ARGV) {
|
||||
$mycallsign = shift @ARGV;
|
||||
$passcode = shift @ARGV;
|
||||
|
@ -45,13 +50,65 @@ my $callsign;
|
|||
|
||||
my $temp;
|
||||
|
||||
# axudp: encodecall: encode single call sign ("AB0CDE-12*") up to 6 letters/numbers, ssid 0..15, optional "*"; last: set in last call sign (dst/via)
|
||||
sub encodecall{
|
||||
my $call = shift;
|
||||
my $last = shift;
|
||||
if(!($call =~ /^([A-Z0-9]{1,6})(-\d+|)(\*|)$/)) {
|
||||
die "Callsign $call not properly formatted";
|
||||
};
|
||||
my $callsign = $1 . ' 'x(6-length($1));
|
||||
my $ssid = length($2)>0 ? 0-$2 : 0;
|
||||
my $hbit = $3 eq '*' ? 0x80 : 0;
|
||||
my $encoded = join('',map chr(ord($_)<<1),split //,$callsign);
|
||||
$encoded .= chr($hbit | 0x60 | ($ssid<<1) | ($last?1:0));
|
||||
return $encoded;
|
||||
}
|
||||
|
||||
# kissmkhead: input: list of callsigns (dest, src, repeater list); output: raw kiss frame header data
|
||||
sub kissmkhead {
|
||||
my @calllist = @_;
|
||||
my $last = pop @calllist;
|
||||
my $enc = join('',map encodecall($_),@calllist);
|
||||
$enc .= encodecall($last, 1);
|
||||
return $enc;
|
||||
}
|
||||
|
||||
#create CRC tab
|
||||
my @CRCL;
|
||||
my @CRCH;
|
||||
my ($c, $crc,$i);
|
||||
for $c (0..255) {
|
||||
$crc = 255-$c;
|
||||
for $i (0..7) { $crc = ($crc&1) ? ($crc>>1)^0x8408 : ($crc>>1); }
|
||||
$CRCL[$c] = $crc&0xff;
|
||||
$CRCH[$c] = (255-($crc>>8))&0xff;
|
||||
}
|
||||
sub appendcrc {
|
||||
$_ = shift;
|
||||
my @data = split //,$_;
|
||||
my ($b, $l, $h)=(0,0,0);
|
||||
for(@data) { $b = ord($_) ^ $l; $l = $CRCL[$b] ^ $h; $h = $CRCH[$b]; }
|
||||
$_ .= chr($l) . chr($h);
|
||||
return $_;
|
||||
}
|
||||
|
||||
my ($sock,$kissheader);
|
||||
if($udp) {
|
||||
my ($udpserver,$udpport)=split ':',$udp;
|
||||
$udpserver = "127.0.0.1" unless $udpserver;
|
||||
$sock = new IO::Socket::INET(PeerAddr => $udpserver, PeerPort => $udpport, Proto => "udp", Timeout => 1) or die "Error creating socket";
|
||||
# $kissheader = kissmkhead("APRS",uc($mycallsign),"TCPIP*");
|
||||
$kissheader = kissmkhead("APRS",uc($mycallsign));
|
||||
}
|
||||
|
||||
print $fpo "user $mycallsign pass $passcode vers \"RS decoder\"\n";
|
||||
|
||||
while ($line = <$fpi>) {
|
||||
|
||||
print STDERR $line; ## entweder: alle Zeilen ausgeben
|
||||
|
||||
if ($line =~ /(\d\d):(\d\d):(\d\d\.?\d?\d?\d?).*\ +lat:\ *(-?\d*)(\.\d*)\ +lon:\ *(-?\d*)(\.\d*)\ +alt:\ *(-?\d*\.\d*).*/) {
|
||||
if ($line =~ /(\d\d):(\d\d):(\d\d\.?\d?\d?\d?).*\ +lat:\ *(-?\d*)(\.\d*).*\ +lon:\ *(-?\d*)(\.\d*).*\ +alt:\ *(-?\d*\.\d*).*/) {
|
||||
|
||||
#print STDERR $line; ## oder: nur Zeile mit Koordinaten ausgeben
|
||||
|
||||
|
@ -78,7 +135,8 @@ while ($line = <$fpi>) {
|
|||
$course = $2;
|
||||
}
|
||||
|
||||
if ($line =~ /\(([\w]+)\)/) {
|
||||
# match either (id) or (type:id) and return id
|
||||
if ($line =~ /\(.*?([\w]+)\)/) {
|
||||
$callsign = $1;
|
||||
}
|
||||
|
||||
|
@ -92,6 +150,11 @@ while ($line = <$fpi>) {
|
|||
$str = sprintf("$mycallsign>APRS,TCPIP*:;%-9s*%06dh%07.2f$NS/%08.2f${EW}O%03d/%03d/A=%06d$comment$temp", $callsign, $hms, $lat, $lon, $course, $speed, $alt);
|
||||
print $fpo "$str\n";
|
||||
|
||||
if($sock) {
|
||||
$str = (split(":",$str))[1];
|
||||
print $sock appendcrc($kissheader.chr(0x03).chr(0xf0).$str);
|
||||
}
|
||||
|
||||
}
|
||||
#elsif ($line =~ / # xdata = (.*)/) { ## nicht, wenn (oben) alle Zeilen ausgeben werden
|
||||
# if ($1) {
|
||||
|
|
Ładowanie…
Reference in New Issue