mirror of
https://github.com/digistump/DigistumpArduino.git
synced 2025-04-27 23:29:01 -07:00
Initial import of support files for all Digistump boards - Digispark, Pro, DigiX - including libraries, examples, tools, and other support files for the Arduino IDE
This commit is contained in:
parent
97abdbf157
commit
7e7473a2d6
65
hardware/digistump/avr/boards.txt
Normal file
65
hardware/digistump/avr/boards.txt
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# See: http://code.google.com/p/arduino/wiki/Platforms
|
||||||
|
|
||||||
|
menu.cpu=Processor
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
digispark-tiny.name=Digispark (Default - 16.5mhz)
|
||||||
|
digispark-tiny.upload.using=micronucleusprog
|
||||||
|
digispark-tiny.upload.protocol=usb
|
||||||
|
digispark-tiny.upload.tool=micronucleus
|
||||||
|
digispark-tiny.upload.maximum_size=6012
|
||||||
|
digispark-tiny.build.mcu=attiny85
|
||||||
|
digispark-tiny.build.f_cpu=16500000L
|
||||||
|
digispark-tiny.build.board=AVR_DIGISPARK
|
||||||
|
digispark-tiny.build.core=tiny
|
||||||
|
digispark-tiny.build.variant=digispark
|
||||||
|
digispark-tiny.upload.wait_for_upload_port = false
|
||||||
|
digispark-tiny.upload.use_1200bps_touch = false
|
||||||
|
digispark-tiny.upload.disable_flushing = false
|
||||||
|
|
||||||
|
|
||||||
|
digispark-pro.name=Digispark Pro (Default 16 Mhz)
|
||||||
|
digispark-pro.upload.using=micronucleusprog
|
||||||
|
digispark-pro.upload.protocol=usb
|
||||||
|
digispark-pro.upload.tool=micronucleus
|
||||||
|
digispark-pro.upload.maximum_size=14844
|
||||||
|
digispark-pro.build.mcu=attiny167
|
||||||
|
digispark-pro.build.f_cpu=16000000L
|
||||||
|
digispark-pro.build.board=AVR_DIGISPARKPRO
|
||||||
|
digispark-pro.build.core=pro
|
||||||
|
digispark-pro.build.variant=pro
|
||||||
|
digispark-pro.upload.wait_for_upload_port = false
|
||||||
|
digispark-pro.upload.use_1200bps_touch = false
|
||||||
|
digispark-pro.upload.disable_flushing = false
|
||||||
|
|
||||||
|
digispark-pro32.name=Digispark Pro (16 Mhz) (32 byte buffer)
|
||||||
|
digispark-pro32.upload.using=micronucleusprog
|
||||||
|
digispark-pro32.upload.protocol=usb
|
||||||
|
digispark-pro32.upload.tool=micronucleus
|
||||||
|
digispark-pro32.upload.maximum_size=14844
|
||||||
|
digispark-pro32.build.mcu=attiny167
|
||||||
|
digispark-pro32.build.f_cpu=16000000L
|
||||||
|
digispark-pro32.build.board=AVR_DIGISPARKPRO
|
||||||
|
digispark-pro32.build.core=pro
|
||||||
|
digispark-pro32.build.variant=pro32buffer
|
||||||
|
digispark-pro32.upload.wait_for_upload_port = false
|
||||||
|
digispark-pro32.upload.use_1200bps_touch = false
|
||||||
|
digispark-pro32.upload.disable_flushing = false
|
||||||
|
|
||||||
|
digispark-pro64.name=Digispark Pro (16 Mhz) (64 byte buffer)
|
||||||
|
digispark-pro64.upload.using=micronucleusprog
|
||||||
|
digispark-pro64.upload.protocol=usb
|
||||||
|
digispark-pro64.upload.tool=micronucleus
|
||||||
|
digispark-pro64.upload.maximum_size=14844
|
||||||
|
digispark-pro64.build.mcu=attiny167
|
||||||
|
digispark-pro64.build.f_cpu=16000000L
|
||||||
|
digispark-pro64.build.board=AVR_DIGISPARKPRO
|
||||||
|
digispark-pro64.build.core=pro
|
||||||
|
digispark-pro64.build.variant=pro64buffer
|
||||||
|
digispark-pro64.upload.wait_for_upload_port = false
|
||||||
|
digispark-pro64.upload.use_1200bps_touch = false
|
||||||
|
digispark-pro64.upload.disable_flushing = false
|
465
hardware/digistump/avr/cores/license.txt
Normal file
465
hardware/digistump/avr/cores/license.txt
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
.....................................................................
|
||||||
|
|
||||||
|
This file includes licensing information for Arduino-Tiny. The GNU
|
||||||
|
Lesser General Public License covers Arduino-Tiny.
|
||||||
|
|
||||||
|
.....................................................................
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
.....................................................................
|
274
hardware/digistump/avr/cores/pro/Arduino.h
Normal file
274
hardware/digistump/avr/cores/pro/Arduino.h
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
#ifndef Arduino_h
|
||||||
|
#define Arduino_h
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#include "binary.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATTINY_CORE 1
|
||||||
|
|
||||||
|
#define HIGH 0x1
|
||||||
|
#define LOW 0x0
|
||||||
|
|
||||||
|
#define INPUT 0x0
|
||||||
|
#define OUTPUT 0x1
|
||||||
|
#define INPUT_PULLUP 0x2
|
||||||
|
|
||||||
|
#define true 0x1
|
||||||
|
#define false 0x0
|
||||||
|
|
||||||
|
#define PI 3.1415926535897932384626433832795
|
||||||
|
#define HALF_PI 1.5707963267948966192313216916398
|
||||||
|
#define TWO_PI 6.283185307179586476925286766559
|
||||||
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
|
|
||||||
|
#define SERIAL 0x0
|
||||||
|
#define DISPLAY 0x1
|
||||||
|
|
||||||
|
#define LSBFIRST 0
|
||||||
|
#define MSBFIRST 1
|
||||||
|
|
||||||
|
#define CHANGE 1
|
||||||
|
#define FALLING 2
|
||||||
|
#define RISING 3
|
||||||
|
|
||||||
|
// undefine stdlib's abs if encountered
|
||||||
|
#ifdef abs
|
||||||
|
#undef abs
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define min(a,b) ((a)<(b)?(a):(b))
|
||||||
|
#define max(a,b) ((a)>(b)?(a):(b))
|
||||||
|
#define abs(x) ((x)>0?(x):-(x))
|
||||||
|
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||||
|
#if __AVR_LIBC_VERSION__ < 10701UL
|
||||||
|
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||||
|
#endif
|
||||||
|
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||||
|
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||||
|
#define sq(x) ((x)*(x))
|
||||||
|
|
||||||
|
#define interrupts() sei()
|
||||||
|
#define noInterrupts() cli()
|
||||||
|
|
||||||
|
#if F_CPU < 1000000L
|
||||||
|
//Prevent a divide by 0 is
|
||||||
|
#warning Clocks per microsecond < 1. To prevent divide by 0, it is rounded up to 1.
|
||||||
|
static inline unsigned long clockCyclesPerMicrosecond() __attribute__ ((always_inline));
|
||||||
|
static inline unsigned long clockCyclesPerMicrosecond()
|
||||||
|
{
|
||||||
|
//Inline function will be optimised out.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
|
||||||
|
#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )
|
||||||
|
|
||||||
|
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||||
|
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||||
|
|
||||||
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||||
|
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||||
|
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
|
||||||
|
|
||||||
|
|
||||||
|
typedef unsigned int word;
|
||||||
|
|
||||||
|
#define bit(b) (1UL << (b))
|
||||||
|
|
||||||
|
typedef uint8_t boolean;
|
||||||
|
typedef uint8_t byte;
|
||||||
|
|
||||||
|
void initToneTimer(void);
|
||||||
|
void init(void);
|
||||||
|
|
||||||
|
void pinMode(uint8_t, uint8_t);
|
||||||
|
void digitalWrite(uint8_t, uint8_t);
|
||||||
|
int digitalRead(uint8_t);
|
||||||
|
int analogRead(uint8_t);
|
||||||
|
void analogReference(uint8_t mode);
|
||||||
|
void analogWrite(uint8_t, int);
|
||||||
|
|
||||||
|
unsigned long millis(void);
|
||||||
|
unsigned long micros(void);
|
||||||
|
void delay(unsigned long);
|
||||||
|
void delayMicroseconds(unsigned int us);
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||||
|
|
||||||
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||||
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
||||||
|
|
||||||
|
void attachInterrupt(uint8_t, void (*)(void), int mode);
|
||||||
|
void detachInterrupt(uint8_t);
|
||||||
|
|
||||||
|
void setup(void);
|
||||||
|
void loop(void);
|
||||||
|
|
||||||
|
// Get the bit location within the hardware port of the given virtual pin.
|
||||||
|
// This comes from the pins_*.c file for the active board configuration.
|
||||||
|
|
||||||
|
#define analogInPinToBit(P) (P)
|
||||||
|
|
||||||
|
extern const uint16_t PROGMEM port_to_mode_PGM[];
|
||||||
|
extern const uint16_t PROGMEM port_to_input_PGM[];
|
||||||
|
extern const uint16_t PROGMEM port_to_output_PGM[];
|
||||||
|
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
|
||||||
|
|
||||||
|
// Get the bit location within the hardware port of the given virtual pin.
|
||||||
|
// This comes from the pins_*.c file for the active board configuration.
|
||||||
|
//
|
||||||
|
// These perform slightly better as macros compared to inline functions
|
||||||
|
//
|
||||||
|
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
|
||||||
|
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
|
||||||
|
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
|
||||||
|
#define analogInPinToBit(P) (P)
|
||||||
|
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
|
||||||
|
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
|
||||||
|
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
|
||||||
|
|
||||||
|
#define NOT_A_PIN 0
|
||||||
|
#define NOT_A_PORT 0
|
||||||
|
|
||||||
|
#define PA 1
|
||||||
|
#define PB 2
|
||||||
|
#define PC 3
|
||||||
|
#define PD 4
|
||||||
|
|
||||||
|
#define NOT_ON_TIMER 0
|
||||||
|
#define TIMER0A 1
|
||||||
|
#define TIMER0B 2
|
||||||
|
#define TIMER1A 3
|
||||||
|
#define TIMER1B 4
|
||||||
|
#define TIMER1D 5
|
||||||
|
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
#ifndef USE_SOFTWARE_SERIAL
|
||||||
|
//Default to hardware serial.
|
||||||
|
#define USE_SOFTWARE_SERIAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Allow the ADC to be optional for low-power applications
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#ifndef TIMER_TO_USE_FOR_MILLIS
|
||||||
|
#define TIMER_TO_USE_FOR_MILLIS 0
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
Tone goes on whichever timer was not used for millis.
|
||||||
|
*/
|
||||||
|
#if TIMER_TO_USE_FOR_MILLIS == 1
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 0
|
||||||
|
#else
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUM_ANALOG_INPUTS > 0
|
||||||
|
#define HAVE_ADC 1
|
||||||
|
#ifndef INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
|
||||||
|
#define INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER 1
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define HAVE_ADC 0
|
||||||
|
#if defined(INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER)
|
||||||
|
#undef INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
|
||||||
|
#endif
|
||||||
|
#define INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !HAVE_ADC
|
||||||
|
#undef INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
|
||||||
|
#define INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER 0
|
||||||
|
#else
|
||||||
|
#ifndef INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
|
||||||
|
#define INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Allow the "secondary timers" to be optional for low-power applications
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#ifndef INITIALIZE_SECONDARY_TIMERS
|
||||||
|
#define INITIALIZE_SECONDARY_TIMERS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include "WCharacter.h"
|
||||||
|
#include "WString.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
#include "TinySoftwareSerial.h"
|
||||||
|
|
||||||
|
uint16_t makeWord(uint16_t w);
|
||||||
|
uint16_t makeWord(byte h, byte l);
|
||||||
|
|
||||||
|
#define word(...) makeWord(__VA_ARGS__)
|
||||||
|
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
|
|
||||||
|
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
|
||||||
|
void noTone(uint8_t _pin = 255);
|
||||||
|
|
||||||
|
// WMath prototypes
|
||||||
|
long random(long);
|
||||||
|
long random(long, long);
|
||||||
|
void randomSeed(unsigned int);
|
||||||
|
long map(long, long, long, long, long);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Aliases for the interrupt service routine vector numbers so the code
|
||||||
|
doesn't have to be riddled with #ifdefs.
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( TIM0_COMPA_vect ) && ! defined( TIMER0_COMPA_vect )
|
||||||
|
#define TIMER0_COMPA_vect TIM0_COMPA_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TIM0_COMPB_vect ) && ! defined( TIMER0_COMPB_vect )
|
||||||
|
#define TIMER0_COMPB_vect TIM0_COMPB_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TIM0_OVF_vect ) && ! defined( TIMER0_OVF_vect )
|
||||||
|
#define TIMER0_OVF_vect TIM0_OVF_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TIM1_COMPA_vect ) && ! defined( TIMER1_COMPA_vect )
|
||||||
|
#define TIMER1_COMPA_vect TIM1_COMPA_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TIM1_COMPB_vect ) && ! defined( TIMER1_COMPB_vect )
|
||||||
|
#define TIMER1_COMPB_vect TIM1_COMPB_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TIM1_OVF_vect ) && ! defined( TIMER1_OVF_vect )
|
||||||
|
#define TIMER1_OVF_vect TIM1_OVF_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
411
hardware/digistump/avr/cores/pro/HardwareSerial.cpp
Normal file
411
hardware/digistump/avr/cores/pro/HardwareSerial.cpp
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
/*
|
||||||
|
HardwareSerial.cpp - Hardware serial library for Wiring
|
||||||
|
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 23 November 2006 by David A. Mellis
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
// this next line disables the entire HardwareSerial.cpp,
|
||||||
|
// this is so I can support Attiny series and any other chip without a uart
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(LINBRRH)) && !USE_SOFTWARE_SERIAL
|
||||||
|
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
|
||||||
|
// Define constants and variables for buffering incoming serial data. We're
|
||||||
|
// using a ring buffer (I think), in which rx_buffer_head is the index of the
|
||||||
|
// location to which to write the next incoming character and rx_buffer_tail
|
||||||
|
// is the index of the location from which to read.
|
||||||
|
#ifndef SERIAL_BUFFER_SIZE
|
||||||
|
#if (RAMEND < 1000)
|
||||||
|
#define SERIAL_BUFFER_SIZE 16
|
||||||
|
#else
|
||||||
|
#define SERIAL_BUFFER_SIZE 64
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
struct ring_buffer
|
||||||
|
{
|
||||||
|
unsigned char buffer[SERIAL_BUFFER_SIZE];
|
||||||
|
byte head;
|
||||||
|
byte tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(UBRRH) || defined(UBRR0H) || defined(LINBRRH)
|
||||||
|
ring_buffer rx_buffer = { { 0 }, 0, 0 };
|
||||||
|
ring_buffer tx_buffer = { { 0 }, 0, 0 };
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR1H)
|
||||||
|
ring_buffer rx_buffer1 = { { 0 }, 0, 0 };
|
||||||
|
ring_buffer tx_buffer1 = { { 0 }, 0, 0 };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void store_char(unsigned char c, ring_buffer *buffer)
|
||||||
|
{
|
||||||
|
byte i = (buffer->head + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
|
||||||
|
// if we should be storing the received character into the location
|
||||||
|
// just before the tail (meaning that the head would advance to the
|
||||||
|
// current location of the tail), we're about to overflow the buffer
|
||||||
|
// and so we don't write the character or advance the head.
|
||||||
|
if (i != buffer->tail) {
|
||||||
|
buffer->buffer[buffer->head] = c;
|
||||||
|
buffer->head = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USART_RX_vect)
|
||||||
|
SIGNAL(USART_RX_vect)
|
||||||
|
{
|
||||||
|
#if defined(UDR0)
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
#elif defined(UDR)
|
||||||
|
unsigned char c = UDR; // atmega8535
|
||||||
|
#else
|
||||||
|
#error UDR not defined
|
||||||
|
#endif
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_USART0_RECV) && defined(UDR0)
|
||||||
|
SIGNAL(SIG_USART0_RECV)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_UART0_RECV) && defined(UDR0)
|
||||||
|
SIGNAL(SIG_UART0_RECV)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
//#elif defined(SIG_USART_RECV)
|
||||||
|
#elif defined(USART0_RX_vect)
|
||||||
|
// fixed by Mark Sproul this is on the 644/644p
|
||||||
|
//SIGNAL(SIG_USART_RECV)
|
||||||
|
SIGNAL(USART0_RX_vect)
|
||||||
|
{
|
||||||
|
#if defined(UDR0)
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
#elif defined(UDR)
|
||||||
|
unsigned char c = UDR; // atmega8, atmega32
|
||||||
|
#else
|
||||||
|
#error UDR not defined
|
||||||
|
#endif
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_UART_RECV)
|
||||||
|
// this is for atmega8
|
||||||
|
SIGNAL(SIG_UART_RECV)
|
||||||
|
{
|
||||||
|
#if defined(UDR0)
|
||||||
|
unsigned char c = UDR0; // atmega645
|
||||||
|
#elif defined(UDR)
|
||||||
|
unsigned char c = UDR; // atmega8
|
||||||
|
#endif
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(LIN_TC_vect)
|
||||||
|
// this is for attinyX7
|
||||||
|
SIGNAL(LIN_TC_vect)
|
||||||
|
{
|
||||||
|
if(LINSIR & _BV(LRXOK)) {
|
||||||
|
unsigned char c = LINDAT;
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
if(LINSIR & _BV(LTXOK)){
|
||||||
|
PINA |= _BV(PINA5);
|
||||||
|
if (tx_buffer.head == tx_buffer.tail) {
|
||||||
|
// Buffer empty, so disable interrupts
|
||||||
|
cbi(LINENIR,LENTXOK);
|
||||||
|
} else {
|
||||||
|
// There is more data in the output buffer. Send the next byte
|
||||||
|
unsigned char c = tx_buffer.buffer[tx_buffer.tail];
|
||||||
|
tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
|
||||||
|
LINDAT = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error No interrupt handler for usart 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#if defined(SIG_USART1_RECV)
|
||||||
|
#if defined(USART1_RX_vect)
|
||||||
|
//SIGNAL(SIG_USART1_RECV)
|
||||||
|
SIGNAL(USART1_RX_vect)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR1;
|
||||||
|
store_char(c, &rx_buffer1);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_USART1_RECV)
|
||||||
|
#error SIG_USART1_RECV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect) && !defined(LIN_TC_vect)
|
||||||
|
#error "Don't know what the Data Register Empty vector is called for the first UART"
|
||||||
|
#elif ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H))
|
||||||
|
#if defined(UART0_UDRE_vect)
|
||||||
|
ISR(UART0_UDRE_vect)
|
||||||
|
#elif defined(UART_UDRE_vect)
|
||||||
|
ISR(UART_UDRE_vect)
|
||||||
|
#elif defined(USART0_UDRE_vect)
|
||||||
|
ISR(USART0_UDRE_vect)
|
||||||
|
#elif defined(USART_UDRE_vect)
|
||||||
|
ISR(USART_UDRE_vect)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (tx_buffer.head == tx_buffer.tail) {
|
||||||
|
// Buffer empty, so disable interrupts
|
||||||
|
#if defined(UCSR0B)
|
||||||
|
cbi(UCSR0B, UDRIE0);
|
||||||
|
#else
|
||||||
|
cbi(UCSRB, UDRIE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// There is more data in the output buffer. Send the next byte
|
||||||
|
unsigned char c = tx_buffer.buffer[tx_buffer.tail];
|
||||||
|
tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
|
||||||
|
#if defined(UDR0)
|
||||||
|
UDR0 = c;
|
||||||
|
#elif defined(UDR)
|
||||||
|
UDR = c;
|
||||||
|
#else
|
||||||
|
#error UDR not defined
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USART1_UDRE_vect
|
||||||
|
ISR(USART1_UDRE_vect)
|
||||||
|
{
|
||||||
|
if (tx_buffer1.head == tx_buffer1.tail) {
|
||||||
|
// Buffer empty, so disable interrupts
|
||||||
|
cbi(UCSR1B, UDRIE1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// There is more data in the output buffer. Send the next byte
|
||||||
|
unsigned char c = tx_buffer1.buffer[tx_buffer1.tail];
|
||||||
|
tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
|
||||||
|
UDR1 = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H))
|
||||||
|
,
|
||||||
|
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
|
||||||
|
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
|
||||||
|
volatile uint8_t *udr,
|
||||||
|
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_rx_buffer = rx_buffer;
|
||||||
|
_tx_buffer = tx_buffer;
|
||||||
|
_ubrrh = ubrrh;
|
||||||
|
_ubrrl = ubrrl;
|
||||||
|
_ucsra = ucsra;
|
||||||
|
_ucsrb = ucsrb;
|
||||||
|
_udr = udr;
|
||||||
|
_rxen = rxen;
|
||||||
|
_txen = txen;
|
||||||
|
_rxcie = rxcie;
|
||||||
|
_udrie = udrie;
|
||||||
|
_u2x = u2x;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_rx_buffer = rx_buffer;
|
||||||
|
_tx_buffer = tx_buffer;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void HardwareSerial::begin(long baud)
|
||||||
|
{
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H))
|
||||||
|
uint16_t baud_setting;
|
||||||
|
bool use_u2x = true;
|
||||||
|
|
||||||
|
#if F_CPU == 16000000UL
|
||||||
|
// hardcoded exception for compatibility with the bootloader shipped
|
||||||
|
// with the Duemilanove and previous boards and the firmware on the 8U2
|
||||||
|
// on the Uno and Mega 2560.
|
||||||
|
if (baud == 57600) {
|
||||||
|
use_u2x = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
try_again:
|
||||||
|
|
||||||
|
if (use_u2x) {
|
||||||
|
*_ucsra = 1 << _u2x;
|
||||||
|
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||||
|
} else {
|
||||||
|
*_ucsra = 0;
|
||||||
|
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((baud_setting > 4095) && use_u2x)
|
||||||
|
{
|
||||||
|
use_u2x = false;
|
||||||
|
goto try_again;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
||||||
|
*_ubrrh = baud_setting >> 8;
|
||||||
|
*_ubrrl = baud_setting;
|
||||||
|
|
||||||
|
sbi(*_ucsrb, _rxen);
|
||||||
|
sbi(*_ucsrb, _txen);
|
||||||
|
sbi(*_ucsrb, _rxcie);
|
||||||
|
cbi(*_ucsrb, _udrie);
|
||||||
|
#else
|
||||||
|
LINCR = (1 << LSWRES);
|
||||||
|
LINBRR = (((F_CPU * 10L / 16L / baud) + 5L) / 10L) - 1;
|
||||||
|
LINBTR = (1 << LDISR) | (16 << LBT0);
|
||||||
|
LINCR = _BV(LENA) | _BV(LCMD2) | _BV(LCMD1) | _BV(LCMD0);
|
||||||
|
sbi(LINENIR,LENRXOK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::end()
|
||||||
|
{
|
||||||
|
while (_tx_buffer->head != _tx_buffer->tail)
|
||||||
|
;
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H))
|
||||||
|
cbi(*_ucsrb, _rxen);
|
||||||
|
cbi(*_ucsrb, _txen);
|
||||||
|
cbi(*_ucsrb, _rxcie);
|
||||||
|
cbi(*_ucsrb, _udrie);
|
||||||
|
#else
|
||||||
|
cbi(LINENIR,LENTXOK);
|
||||||
|
cbi(LINENIR,LENRXOK);
|
||||||
|
cbi(LINCR,LENA);
|
||||||
|
cbi(LINCR,LCMD0);
|
||||||
|
cbi(LINCR,LCMD1);
|
||||||
|
cbi(LINCR,LCMD2);
|
||||||
|
#endif
|
||||||
|
_rx_buffer->head = _rx_buffer->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::available(void)
|
||||||
|
{
|
||||||
|
return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::peek(void)
|
||||||
|
{
|
||||||
|
if (_rx_buffer->head == _rx_buffer->tail) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return _rx_buffer->buffer[_rx_buffer->tail];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::read(void)
|
||||||
|
{
|
||||||
|
// if the head isn't ahead of the tail, we don't have any characters
|
||||||
|
if (_rx_buffer->head == _rx_buffer->tail) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
|
||||||
|
_rx_buffer->tail = (_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::flush()
|
||||||
|
{
|
||||||
|
while (_tx_buffer->head != _tx_buffer->tail)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int HardwareSerial::txfree()
|
||||||
|
{
|
||||||
|
if (_tx_buffer->head >= _tx_buffer->tail) return SERIAL_BUFFER_SIZE - 1 - _tx_buffer->head + _tx_buffer->tail;
|
||||||
|
return _tx_buffer->tail - _tx_buffer->head - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t HardwareSerial::write(uint8_t c)
|
||||||
|
{
|
||||||
|
byte i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
|
||||||
|
// If the output buffer is full, there's nothing for it other than to
|
||||||
|
// wait for the interrupt handler to empty it a bit
|
||||||
|
// ???: return 0 here instead?
|
||||||
|
while (txfree() == 0);
|
||||||
|
|
||||||
|
_tx_buffer->buffer[_tx_buffer->head] = c;
|
||||||
|
_tx_buffer->head = i;
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) )
|
||||||
|
sbi(*_ucsrb, _udrie);
|
||||||
|
#else
|
||||||
|
if(!(LINENIR & _BV(LENTXOK))){
|
||||||
|
//The buffer was previously empty, so enable TX Complete interrupt and load first byte.
|
||||||
|
sbi(LINENIR,LENTXOK);
|
||||||
|
unsigned char c = tx_buffer.buffer[tx_buffer.tail];
|
||||||
|
tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
LINDAT = c;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HardwareSerial::operator bool() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(UBRRH) && defined(UBRRL)
|
||||||
|
HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);
|
||||||
|
#elif defined(UBRR0H) && defined(UBRR0L)
|
||||||
|
HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0);
|
||||||
|
#elif defined(LINBRRH)
|
||||||
|
HardwareSerial Serial(&rx_buffer, &tx_buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(UBRR1H)
|
||||||
|
HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif !USE_SOFTWARE_SERIAL
|
||||||
|
#warning There is no Hardware UART, and Sofware Serial is not enabled. There will be no serial port.
|
||||||
|
#endif // whole file
|
80
hardware/digistump/avr/cores/pro/HardwareSerial.h
Normal file
80
hardware/digistump/avr/cores/pro/HardwareSerial.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
HardwareSerial.h - Hardware serial library for Wiring
|
||||||
|
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HardwareSerial_h
|
||||||
|
#define HardwareSerial_h
|
||||||
|
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(LINBRRH)) && !USE_SOFTWARE_SERIAL
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
struct ring_buffer;
|
||||||
|
|
||||||
|
class HardwareSerial : public Stream
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ring_buffer *_rx_buffer;
|
||||||
|
ring_buffer *_tx_buffer;
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H))
|
||||||
|
volatile uint8_t *_ubrrh;
|
||||||
|
volatile uint8_t *_ubrrl;
|
||||||
|
volatile uint8_t *_ucsra;
|
||||||
|
volatile uint8_t *_ucsrb;
|
||||||
|
volatile uint8_t *_udr;
|
||||||
|
uint8_t _rxen;
|
||||||
|
uint8_t _txen;
|
||||||
|
uint8_t _rxcie;
|
||||||
|
uint8_t _udrie;
|
||||||
|
uint8_t _u2x;
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer
|
||||||
|
#if ( defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H))
|
||||||
|
,
|
||||||
|
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
|
||||||
|
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
|
||||||
|
volatile uint8_t *udr,
|
||||||
|
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x);
|
||||||
|
#else
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
void begin(long);
|
||||||
|
void end();
|
||||||
|
virtual int available(void);
|
||||||
|
virtual int peek(void);
|
||||||
|
virtual unsigned int txfree(void);
|
||||||
|
virtual int read(void);
|
||||||
|
virtual void flush(void);
|
||||||
|
virtual size_t write(uint8_t);
|
||||||
|
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||||
|
operator bool();
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(UBRRH) || defined(UBRR0H) || defined(LINBRRH)) && !USE_SOFTWARE_SERIAL
|
||||||
|
extern HardwareSerial Serial;
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR1H)
|
||||||
|
extern HardwareSerial Serial1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
262
hardware/digistump/avr/cores/pro/Print.cpp
Normal file
262
hardware/digistump/avr/cores/pro/Print.cpp
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
Print.cpp - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 23 November 2006 by David A. Mellis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* default implementation: may be overridden */
|
||||||
|
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
while (size--) {
|
||||||
|
n += write(*buffer++);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const String &s)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (uint16_t i = 0; i < s.length(); i++) {
|
||||||
|
n += write(s[i]);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(const char str[])
|
||||||
|
{
|
||||||
|
return write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(char c)
|
||||||
|
{
|
||||||
|
return write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
return print((unsigned long) b, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(int n, int base)
|
||||||
|
{
|
||||||
|
return print((long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned int n, int base)
|
||||||
|
{
|
||||||
|
return print((unsigned long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(long n, int base)
|
||||||
|
{
|
||||||
|
if (base == 0) {
|
||||||
|
return write(n);
|
||||||
|
} else if (base == 10) {
|
||||||
|
int t = 0;
|
||||||
|
if (n < 0) {
|
||||||
|
t = print('-');
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
return printNumber(n, 10) + t;
|
||||||
|
} else {
|
||||||
|
return printNumber(n, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(unsigned long n, int base)
|
||||||
|
{
|
||||||
|
if (base == 0) return write(n);
|
||||||
|
else return printNumber(n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(double n, int digits)
|
||||||
|
{
|
||||||
|
return printFloat(n, digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print( fstr_t* s )
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
ch = pgm_read_byte( s );
|
||||||
|
while ( ch != 0 )
|
||||||
|
{
|
||||||
|
write( ch );
|
||||||
|
++s;
|
||||||
|
++n;
|
||||||
|
ch = pgm_read_byte( s );
|
||||||
|
}
|
||||||
|
return( n );
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(void)
|
||||||
|
{
|
||||||
|
size_t n = print('\r');
|
||||||
|
n += print('\n');
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const String &s)
|
||||||
|
{
|
||||||
|
size_t n = print(s);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(const char c[])
|
||||||
|
{
|
||||||
|
size_t n = print(c);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(char c)
|
||||||
|
{
|
||||||
|
size_t n = print(c);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(b, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(int num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned int num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(long long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(unsigned long num, int base)
|
||||||
|
{
|
||||||
|
size_t n = print(num, base);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println(double num, int digits)
|
||||||
|
{
|
||||||
|
size_t n = print(num, digits);
|
||||||
|
n += println();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::println( fstr_t* s )
|
||||||
|
{
|
||||||
|
size_t n = print( s );
|
||||||
|
n += println();
|
||||||
|
return( n );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Methods /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
size_t Print::printNumber(unsigned long n, uint8_t base) {
|
||||||
|
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||||
|
char *str = &buf[sizeof(buf) - 1];
|
||||||
|
|
||||||
|
*str = '\0';
|
||||||
|
|
||||||
|
// prevent crash if called with base == 1
|
||||||
|
if (base < 2) base = 10;
|
||||||
|
|
||||||
|
do {
|
||||||
|
unsigned long m = n;
|
||||||
|
n /= base;
|
||||||
|
char c = m - base * n;
|
||||||
|
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||||
|
} while(n);
|
||||||
|
|
||||||
|
return write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::printFloat(double number, uint8_t digits)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
// Handle negative numbers
|
||||||
|
if (number < 0.0)
|
||||||
|
{
|
||||||
|
n += print('-');
|
||||||
|
number = -number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||||
|
double rounding = 0.5;
|
||||||
|
for (uint8_t i=0; i<digits; ++i)
|
||||||
|
rounding /= 10.0;
|
||||||
|
|
||||||
|
number += rounding;
|
||||||
|
|
||||||
|
// Extract the integer part of the number and print it
|
||||||
|
unsigned long int_part = (unsigned long)number;
|
||||||
|
double remainder = number - (double)int_part;
|
||||||
|
n += print(int_part);
|
||||||
|
|
||||||
|
// Print the decimal point, but only if there are digits beyond
|
||||||
|
if (digits > 0) {
|
||||||
|
n += print(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract digits from the remainder one at a time
|
||||||
|
while (digits-- > 0)
|
||||||
|
{
|
||||||
|
remainder *= 10.0;
|
||||||
|
int toPrint = int(remainder);
|
||||||
|
n += print(toPrint);
|
||||||
|
remainder -= toPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
108
hardware/digistump/avr/cores/pro/Print.h
Normal file
108
hardware/digistump/avr/cores/pro/Print.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
Print.h - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 20-11-2010 by B.Cook ...
|
||||||
|
|
||||||
|
http://arduiniana.org/libraries/flash/
|
||||||
|
Printable support thanks to Mikal Hart
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Print_h
|
||||||
|
#define Print_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h> // for size_t
|
||||||
|
|
||||||
|
#include "WString.h"
|
||||||
|
|
||||||
|
#define DEC 10
|
||||||
|
#define HEX 16
|
||||||
|
#define OCT 8
|
||||||
|
#ifdef BIN
|
||||||
|
#define ABIN BIN
|
||||||
|
//One of the ATtiny84 registers has a bit called BIN, so rename it to avoid compiler warnings.
|
||||||
|
#undef BIN
|
||||||
|
#endif
|
||||||
|
#define BIN 2
|
||||||
|
|
||||||
|
#define ARDUINO_CORE_PRINTABLE_SUPPORT
|
||||||
|
|
||||||
|
class Print;
|
||||||
|
|
||||||
|
/* Printable...*/
|
||||||
|
|
||||||
|
class _Printable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void print(Print &stream) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ...Printable */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
}
|
||||||
|
fstr_t;
|
||||||
|
|
||||||
|
|
||||||
|
class Print
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int write_error;
|
||||||
|
size_t printNumber(unsigned long, uint8_t);
|
||||||
|
size_t printFloat(double, uint8_t);
|
||||||
|
protected:
|
||||||
|
void setWriteError(int err = 1) { write_error = err; }
|
||||||
|
public:
|
||||||
|
Print() : write_error(0) {}
|
||||||
|
|
||||||
|
int getWriteError() { return write_error; }
|
||||||
|
void clearWriteError() { setWriteError(0); }
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t) = 0;
|
||||||
|
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
|
||||||
|
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||||
|
|
||||||
|
size_t print(fstr_t*);
|
||||||
|
size_t print(const String &);
|
||||||
|
size_t print(const char[]);
|
||||||
|
size_t print(char);
|
||||||
|
size_t print(unsigned char, int = DEC);
|
||||||
|
size_t print(int, int = DEC);
|
||||||
|
size_t print(unsigned int, int = DEC);
|
||||||
|
size_t print(long, int = DEC);
|
||||||
|
size_t print(long long, int = DEC);
|
||||||
|
size_t print(unsigned long, int = DEC);
|
||||||
|
size_t print(double, int = 2);
|
||||||
|
|
||||||
|
size_t println(fstr_t*);
|
||||||
|
size_t println(const String &s);
|
||||||
|
size_t println(const char[]);
|
||||||
|
size_t println(char);
|
||||||
|
size_t println(unsigned char, int = DEC);
|
||||||
|
size_t println(int, int = DEC);
|
||||||
|
size_t println(unsigned int, int = DEC);
|
||||||
|
size_t println(long, int = DEC);
|
||||||
|
size_t println(long long, int = DEC);
|
||||||
|
size_t println(unsigned long, int = DEC);
|
||||||
|
size_t println(double, int = 2);
|
||||||
|
size_t println(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
40
hardware/digistump/avr/cores/pro/Printable.h
Normal file
40
hardware/digistump/avr/cores/pro/Printable.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Printable.h - Interface class that allows printing of complex types
|
||||||
|
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Printable_h
|
||||||
|
#define Printable_h
|
||||||
|
|
||||||
|
#include <new.h>
|
||||||
|
|
||||||
|
class Print;
|
||||||
|
|
||||||
|
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
||||||
|
By deriving from Printable and implementing the printTo method, it will then be possible
|
||||||
|
for users to print out instances of this class by passing them into the usual
|
||||||
|
Print::print and Print::println methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Printable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual size_t printTo(Print& p) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
270
hardware/digistump/avr/cores/pro/Stream.cpp
Normal file
270
hardware/digistump/avr/cores/pro/Stream.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
Stream.cpp - adds parsing methods to Stream class
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Created July 2011
|
||||||
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||||
|
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
|
||||||
|
|
||||||
|
// private method to read stream with timeout
|
||||||
|
int Stream::timedRead()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
_startMillis = millis();
|
||||||
|
do {
|
||||||
|
c = read();
|
||||||
|
if (c >= 0) return c;
|
||||||
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// private method to peek stream with timeout
|
||||||
|
int Stream::timedPeek()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
_startMillis = millis();
|
||||||
|
do {
|
||||||
|
c = peek();
|
||||||
|
if (c >= 0) return c;
|
||||||
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns peek of the next digit in the stream or -1 if timeout
|
||||||
|
// discards non-numeric characters
|
||||||
|
int Stream::peekNextDigit()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
while (1) {
|
||||||
|
c = timedPeek();
|
||||||
|
if (c < 0) return c; // timeout
|
||||||
|
if (c == '-') return c;
|
||||||
|
if (c >= '0' && c <= '9') return c;
|
||||||
|
read(); // discard non-numeric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Methods
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||||
|
{
|
||||||
|
_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find returns true if the target string is found
|
||||||
|
bool Stream::find(char *target)
|
||||||
|
{
|
||||||
|
return findUntil(target, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads data from the stream until the target string of given length is found
|
||||||
|
// returns true if target string is found, false if timed out
|
||||||
|
bool Stream::find(char *target, size_t length)
|
||||||
|
{
|
||||||
|
return findUntil(target, length, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// as find but search ends if the terminator string is found
|
||||||
|
bool Stream::findUntil(char *target, char *terminator)
|
||||||
|
{
|
||||||
|
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads data from the stream until the target string of the given length is found
|
||||||
|
// search terminated if the terminator string is found
|
||||||
|
// returns true if target string is found, false if terminated or timed out
|
||||||
|
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
||||||
|
{
|
||||||
|
size_t index = 0; // maximum target string length is 64k bytes!
|
||||||
|
size_t termIndex = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if( *target == 0)
|
||||||
|
return true; // return true if target is a null string
|
||||||
|
while( (c = timedRead()) > 0){
|
||||||
|
|
||||||
|
if(c != target[index])
|
||||||
|
index = 0; // reset index if any char does not match
|
||||||
|
|
||||||
|
if( c == target[index]){
|
||||||
|
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
||||||
|
if(++index >= targetLen){ // return true if all chars in the target match
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(termLen > 0 && c == terminator[termIndex]){
|
||||||
|
if(++termIndex >= termLen)
|
||||||
|
return false; // return false if terminate string found before target string
|
||||||
|
}
|
||||||
|
else
|
||||||
|
termIndex = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns the first valid (long) integer value from the current position.
|
||||||
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
|
// function is terminated by the first character that is not a digit.
|
||||||
|
long Stream::parseInt()
|
||||||
|
{
|
||||||
|
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// as above but a given skipChar is ignored
|
||||||
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
long Stream::parseInt(char skipChar)
|
||||||
|
{
|
||||||
|
boolean isNegative = false;
|
||||||
|
long value = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = peekNextDigit();
|
||||||
|
// ignore non numeric leading characters
|
||||||
|
if(c < 0)
|
||||||
|
return 0; // zero returned if timeout
|
||||||
|
|
||||||
|
do{
|
||||||
|
if(c == skipChar)
|
||||||
|
; // ignore this charactor
|
||||||
|
else if(c == '-')
|
||||||
|
isNegative = true;
|
||||||
|
else if(c >= '0' && c <= '9') // is c a digit?
|
||||||
|
value = value * 10 + c - '0';
|
||||||
|
read(); // consume the character we got with peek
|
||||||
|
c = timedPeek();
|
||||||
|
}
|
||||||
|
while( (c >= '0' && c <= '9') || c == skipChar );
|
||||||
|
|
||||||
|
if(isNegative)
|
||||||
|
value = -value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// as parseInt but returns a floating point value
|
||||||
|
float Stream::parseFloat()
|
||||||
|
{
|
||||||
|
return parseFloat(NO_SKIP_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// as above but the given skipChar is ignored
|
||||||
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
float Stream::parseFloat(char skipChar){
|
||||||
|
boolean isNegative = false;
|
||||||
|
boolean isFraction = false;
|
||||||
|
long value = 0;
|
||||||
|
char c;
|
||||||
|
float fraction = 1.0;
|
||||||
|
|
||||||
|
c = peekNextDigit();
|
||||||
|
// ignore non numeric leading characters
|
||||||
|
if(c < 0)
|
||||||
|
return 0; // zero returned if timeout
|
||||||
|
|
||||||
|
do{
|
||||||
|
if(c == skipChar)
|
||||||
|
; // ignore
|
||||||
|
else if(c == '-')
|
||||||
|
isNegative = true;
|
||||||
|
else if (c == '.')
|
||||||
|
isFraction = true;
|
||||||
|
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||||
|
value = value * 10 + c - '0';
|
||||||
|
if(isFraction)
|
||||||
|
fraction *= 0.1;
|
||||||
|
}
|
||||||
|
read(); // consume the character we got with peek
|
||||||
|
c = timedPeek();
|
||||||
|
}
|
||||||
|
while( (c >= '0' && c <= '9') || c == '.' || c == skipChar );
|
||||||
|
|
||||||
|
if(isNegative)
|
||||||
|
value = -value;
|
||||||
|
if(isFraction)
|
||||||
|
return value * fraction;
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read characters from stream into buffer
|
||||||
|
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||||
|
// returns the number of characters placed in the buffer
|
||||||
|
// the buffer is NOT null terminated.
|
||||||
|
//
|
||||||
|
size_t Stream::readBytes(char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
while (count < length) {
|
||||||
|
int c = timedRead();
|
||||||
|
if (c < 0) break;
|
||||||
|
*buffer++ = (char)c;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// as readBytes with terminator character
|
||||||
|
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
if (length < 1) return 0;
|
||||||
|
size_t index = 0;
|
||||||
|
while (index < length) {
|
||||||
|
int c = timedRead();
|
||||||
|
if (c < 0 || c == terminator) break;
|
||||||
|
*buffer++ = (char)c;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return index; // return number of characters, not including null terminator
|
||||||
|
}
|
||||||
|
|
||||||
|
String Stream::readString()
|
||||||
|
{
|
||||||
|
String ret;
|
||||||
|
int c = timedRead();
|
||||||
|
while (c >= 0)
|
||||||
|
{
|
||||||
|
ret += (char)c;
|
||||||
|
c = timedRead();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Stream::readStringUntil(char terminator)
|
||||||
|
{
|
||||||
|
String ret;
|
||||||
|
int c = timedRead();
|
||||||
|
while (c >= 0 && c != terminator)
|
||||||
|
{
|
||||||
|
ret += (char)c;
|
||||||
|
c = timedRead();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
96
hardware/digistump/avr/cores/pro/Stream.h
Normal file
96
hardware/digistump/avr/cores/pro/Stream.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
Stream.h - base class for character-based streams.
|
||||||
|
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
parsing functions based on TextFinder library by Michael Margolis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Stream_h
|
||||||
|
#define Stream_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
// compatability macros for testing
|
||||||
|
/*
|
||||||
|
#define getInt() parseInt()
|
||||||
|
#define getInt(skipChar) parseInt(skipchar)
|
||||||
|
#define getFloat() parseFloat()
|
||||||
|
#define getFloat(skipChar) parseFloat(skipChar)
|
||||||
|
#define getString( pre_string, post_string, buffer, length)
|
||||||
|
readBytesBetween( pre_string, terminator, buffer, length)
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Stream : public Print
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||||
|
unsigned long _startMillis; // used for timeout measurement
|
||||||
|
int timedRead(); // private method to read stream with timeout
|
||||||
|
int timedPeek(); // private method to peek stream with timeout
|
||||||
|
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual int available() = 0;
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int peek() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
|
||||||
|
Stream() {_timeout=1000;}
|
||||||
|
|
||||||
|
// parsing methods
|
||||||
|
|
||||||
|
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||||
|
|
||||||
|
bool find(char *target); // reads data from the stream until the target string is found
|
||||||
|
// returns true if target string is found, false if timed out (see setTimeout)
|
||||||
|
|
||||||
|
bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||||
|
// returns true if target string is found, false if timed out
|
||||||
|
|
||||||
|
bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
|
||||||
|
|
||||||
|
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||||
|
|
||||||
|
|
||||||
|
long parseInt(); // returns the first valid (long) integer value from the current position.
|
||||||
|
// initial characters that are not digits (or the minus sign) are skipped
|
||||||
|
// integer is terminated by the first character that is not a digit.
|
||||||
|
|
||||||
|
float parseFloat(); // float version of parseInt
|
||||||
|
|
||||||
|
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
||||||
|
// terminates if length characters have been read or timeout (see setTimeout)
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||||
|
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||||
|
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||||
|
|
||||||
|
// Arduino String functions to be added here
|
||||||
|
String readString();
|
||||||
|
String readStringUntil(char terminator);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
||||||
|
// as above but the given skipChar is ignored
|
||||||
|
// this allows format characters (typically commas) in values to be ignored
|
||||||
|
|
||||||
|
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
35
hardware/digistump/avr/cores/pro/Stream_old.h
Normal file
35
hardware/digistump/avr/cores/pro/Stream_old.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Stream.h - base class for character-based streams.
|
||||||
|
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Stream_h
|
||||||
|
#define Stream_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
class Stream : public Print
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int available() = 0;
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int peek() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
218
hardware/digistump/avr/cores/pro/TinySoftwareSPI.cpp
Normal file
218
hardware/digistump/avr/cores/pro/TinySoftwareSPI.cpp
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 by Thomas Carpenter
|
||||||
|
* Software based SPI Master Library for Tiny core.
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of either the GNU General Public License version 2
|
||||||
|
* or the GNU Lesser General Public License version 2.1, both as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Currently, this runs at 125kHz on an 8MHz clock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TinySoftwareSPI.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
SoftSPIClass::SoftSPIClass(){
|
||||||
|
_bitOrder = MSBFIRST;
|
||||||
|
_mode = SPI_MODE0;
|
||||||
|
_running = false;
|
||||||
|
transferType = &SoftSPIClass::noTransfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SS) && defined(MOSI) && defined(MISO) && defined(SCK)
|
||||||
|
void SoftSPIClass::begin(){
|
||||||
|
begin(SCK,MOSI,MISO,SS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SoftSPIClass::writeSS(boolean state){
|
||||||
|
if (state) {
|
||||||
|
*_SS_PORT |= _SS_HIGH;
|
||||||
|
} else {
|
||||||
|
*_SS_PORT &= _SS_LOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftSPIClass::begin(byte SCK_, byte MOSI_, byte MISO_, byte SS_){
|
||||||
|
_SS = SS_;
|
||||||
|
_SCK = SCK_;
|
||||||
|
_MISO = MISO_;
|
||||||
|
_MOSI = MOSI_;
|
||||||
|
|
||||||
|
byte MOSIport = digitalPinToPort(_MOSI);
|
||||||
|
byte SSport = digitalPinToPort(_SS);
|
||||||
|
byte SCKport = digitalPinToPort(_SCK);
|
||||||
|
byte MISOport = digitalPinToPort(_MISO);
|
||||||
|
|
||||||
|
if ((MOSIport == NOT_A_PIN) ||
|
||||||
|
( SSport == NOT_A_PIN) ||
|
||||||
|
( SCKport == NOT_A_PIN) ||
|
||||||
|
(MISOport == NOT_A_PIN) ){
|
||||||
|
end();
|
||||||
|
} else {
|
||||||
|
_running = true;
|
||||||
|
pinMode(_MOSI, OUTPUT);
|
||||||
|
pinMode(_MISO, INPUT);
|
||||||
|
pinMode(_SCK, OUTPUT);
|
||||||
|
pinMode(_SS, OUTPUT);
|
||||||
|
_MOSI_PORT = portOutputRegister(MOSIport);
|
||||||
|
_MOSI_HIGH = digitalPinToBitMask(_MOSI);
|
||||||
|
_MOSI_LOW = ~_MOSI_HIGH;
|
||||||
|
_SCK_PORT = portOutputRegister(SCKport);
|
||||||
|
_SCK_HIGH = digitalPinToBitMask(_SCK);
|
||||||
|
_SCK_LOW = ~_SCK_HIGH;
|
||||||
|
_SS_PORT = portOutputRegister(SSport);
|
||||||
|
_SS_HIGH = digitalPinToBitMask(_SS);
|
||||||
|
_SS_LOW = ~_SS_HIGH;
|
||||||
|
_MISO_PIN = portInputRegister(MISOport);
|
||||||
|
_MISO_MASK = digitalPinToBitMask(_MISO);
|
||||||
|
*_SS_PORT |= _SS_HIGH;
|
||||||
|
*_SCK_PORT &= _SCK_LOW;
|
||||||
|
*_MOSI_PORT &= _MOSI_LOW;
|
||||||
|
|
||||||
|
//Default to Mode0.
|
||||||
|
_mode = SPI_MODE0;
|
||||||
|
transferType = &SoftSPIClass::transferMode0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte SoftSPIClass::noTransfer(byte _data){
|
||||||
|
//This does nothing. If you call SPI.transfer() before calling begin() or after calling end(), the call will be redirected here to avoid crash.
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte SoftSPIClass::transferMode0(byte _data){
|
||||||
|
byte _newData = 0;
|
||||||
|
for (byte i = 0;i < 8; i++){
|
||||||
|
if(_data & 0x80){
|
||||||
|
*_MOSI_PORT |= _MOSI_HIGH;
|
||||||
|
} else {
|
||||||
|
*_MOSI_PORT &= _MOSI_LOW;
|
||||||
|
}
|
||||||
|
_data <<= 1;
|
||||||
|
*_SCK_PORT |= _SCK_HIGH;
|
||||||
|
_newData <<= 1;
|
||||||
|
_newData |= ((*_MISO_PIN & _MISO_MASK) ? 1 : 0);
|
||||||
|
*_SCK_PORT &= _SCK_LOW;
|
||||||
|
}
|
||||||
|
return _newData;
|
||||||
|
}
|
||||||
|
byte SoftSPIClass::transferMode1(byte _data){
|
||||||
|
byte _newData = 0;
|
||||||
|
for (byte i = 0;i < 8; i++){
|
||||||
|
*_SCK_PORT |= _SCK_HIGH;
|
||||||
|
if(_data & 0x80){
|
||||||
|
*_MOSI_PORT |= _MOSI_HIGH;
|
||||||
|
} else {
|
||||||
|
*_MOSI_PORT &= _MOSI_LOW;
|
||||||
|
}
|
||||||
|
_data <<= 1;
|
||||||
|
*_SCK_PORT &= _SCK_LOW;
|
||||||
|
_newData <<= 1;
|
||||||
|
_newData |= ((*_MISO_PIN & _MISO_MASK) ? 1 : 0);
|
||||||
|
}
|
||||||
|
return _newData;
|
||||||
|
}
|
||||||
|
byte SoftSPIClass::transferMode2(byte _data){
|
||||||
|
byte _newData = 0;
|
||||||
|
for (byte i = 0;i < 8; i++){
|
||||||
|
if(_data & 0x80){
|
||||||
|
*_MOSI_PORT |= _MOSI_HIGH;
|
||||||
|
} else {
|
||||||
|
*_MOSI_PORT &= _MOSI_LOW;
|
||||||
|
}
|
||||||
|
_data <<= 1;
|
||||||
|
*_SCK_PORT &= _SCK_LOW;
|
||||||
|
_newData <<= 1;
|
||||||
|
_newData |= ((*_MISO_PIN & _MISO_MASK) ? 1 : 0);
|
||||||
|
*_SCK_PORT |= _SCK_HIGH;
|
||||||
|
}
|
||||||
|
return _newData;
|
||||||
|
}
|
||||||
|
byte SoftSPIClass::transferMode3(byte _data){
|
||||||
|
byte _newData = 0;
|
||||||
|
for (byte i = 0;i < 8; i++){
|
||||||
|
*_SCK_PORT &= _SCK_LOW;
|
||||||
|
if(_data & 0x80){
|
||||||
|
*_MOSI_PORT |= _MOSI_HIGH;
|
||||||
|
} else {
|
||||||
|
*_MOSI_PORT &= _MOSI_LOW;
|
||||||
|
}
|
||||||
|
_data <<= 1;
|
||||||
|
*_SCK_PORT |= _SCK_HIGH;
|
||||||
|
_newData <<= 1;
|
||||||
|
_newData |= ((*_MISO_PIN & _MISO_MASK) ? 1 : 0);
|
||||||
|
}
|
||||||
|
return _newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte SoftSPIClass::transfer(byte _data){
|
||||||
|
byte _newData = 0;
|
||||||
|
byte oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
if (_bitOrder == MSBFIRST){
|
||||||
|
//Send data
|
||||||
|
_newData = (*this.*transferType)(_data);
|
||||||
|
SREG = oldSREG;
|
||||||
|
return _newData;
|
||||||
|
} else {
|
||||||
|
//flip the data
|
||||||
|
for(byte i = 0; i < 8; i++){
|
||||||
|
_newData <<= 1;
|
||||||
|
_newData |= _data & 1;
|
||||||
|
_data >>= 1;
|
||||||
|
}
|
||||||
|
//SPI transfer
|
||||||
|
_newData = (*this.*transferType)(_newData);
|
||||||
|
SREG = oldSREG;
|
||||||
|
//flip data back.
|
||||||
|
_data = 0;
|
||||||
|
for(byte i = 0; i < 8; i++){
|
||||||
|
_data <<= 1;
|
||||||
|
_data |= _newData & 1;
|
||||||
|
_newData >>= 1;
|
||||||
|
}
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftSPIClass::end(){
|
||||||
|
_running = false;
|
||||||
|
transferType = &SoftSPIClass::noTransfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftSPIClass::setBitOrder(uint8_t bitOrder) {
|
||||||
|
_bitOrder = bitOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftSPIClass::setDataMode(uint8_t mode)
|
||||||
|
{
|
||||||
|
_mode = mode;
|
||||||
|
if(_mode == SPI_MODE0){
|
||||||
|
transferType = &SoftSPIClass::transferMode0;
|
||||||
|
} else if (_mode == SPI_MODE1){
|
||||||
|
transferType = &SoftSPIClass::transferMode1;
|
||||||
|
} else if (_mode == SPI_MODE2){
|
||||||
|
transferType = &SoftSPIClass::transferMode2;
|
||||||
|
} else if (_mode == SPI_MODE3){
|
||||||
|
transferType = &SoftSPIClass::transferMode3;
|
||||||
|
} else {
|
||||||
|
_mode = SPI_MODE0;
|
||||||
|
transferType = &SoftSPIClass::transferMode0;
|
||||||
|
}
|
||||||
|
if(_mode & 0x02){
|
||||||
|
*_SCK_PORT |= _SCK_HIGH;
|
||||||
|
} else {
|
||||||
|
*_SCK_PORT &= _SCK_LOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftSPIClass::setClockDivider(uint8_t rate)
|
||||||
|
{
|
||||||
|
|
||||||
|
//does nothing as the speed cannot be changed - fixed at Fcpu/16
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SoftSPIClass SPI;
|
83
hardware/digistump/avr/cores/pro/TinySoftwareSPI.h
Normal file
83
hardware/digistump/avr/cores/pro/TinySoftwareSPI.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 by Thomas Carpenter
|
||||||
|
* Software based SPI Master Library for Tiny core.
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of either the GNU General Public License version 2
|
||||||
|
* or the GNU Lesser General Public License version 2.1, both as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SPI_H_INCLUDED
|
||||||
|
//Uses the same guard as the SPI class as the two cannot be used together
|
||||||
|
#define _SPI_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define SPI_MODE0 0
|
||||||
|
#define SPI_MODE1 1
|
||||||
|
#define SPI_MODE2 2
|
||||||
|
#define SPI_MODE3 3
|
||||||
|
|
||||||
|
#define SPI_CLOCK_DIV4 0x00
|
||||||
|
#define SPI_CLOCK_DIV16 0x01
|
||||||
|
#define SPI_CLOCK_DIV64 0x02
|
||||||
|
#define SPI_CLOCK_DIV128 0x03
|
||||||
|
#define SPI_CLOCK_DIV2 0x04
|
||||||
|
#define SPI_CLOCK_DIV8 0x05
|
||||||
|
#define SPI_CLOCK_DIV32 0x06
|
||||||
|
|
||||||
|
class SoftSPIClass;
|
||||||
|
typedef byte (SoftSPIClass::*TransferFunction)(byte _data);
|
||||||
|
|
||||||
|
class SoftSPIClass {
|
||||||
|
public:
|
||||||
|
SoftSPIClass();
|
||||||
|
private:
|
||||||
|
TransferFunction transferType;
|
||||||
|
byte noTransfer(byte _data);
|
||||||
|
byte transferMode0(byte _data);
|
||||||
|
byte transferMode1(byte _data);
|
||||||
|
byte transferMode2(byte _data);
|
||||||
|
byte transferMode3(byte _data);
|
||||||
|
public:
|
||||||
|
byte transfer(byte _data);
|
||||||
|
|
||||||
|
// SPI Configuration methods
|
||||||
|
#if defined(SS) && defined(MOSI) && defined(MISO) && defined(SCK)
|
||||||
|
void begin(); // Default to the preset SPI pins
|
||||||
|
#endif
|
||||||
|
void begin(byte SCK_, byte MOSI_, byte MISO_, byte SS_); //No SS specified, so require pin designation
|
||||||
|
void end();
|
||||||
|
|
||||||
|
void setBitOrder(uint8_t);
|
||||||
|
void setDataMode(uint8_t);
|
||||||
|
void setClockDivider(uint8_t);
|
||||||
|
|
||||||
|
void writeSS(boolean state);
|
||||||
|
private:
|
||||||
|
byte _rate;
|
||||||
|
byte _bitOrder;
|
||||||
|
byte _mode;
|
||||||
|
boolean _running;
|
||||||
|
byte _SS;
|
||||||
|
byte _SCK;
|
||||||
|
byte _MISO;
|
||||||
|
byte _MOSI;
|
||||||
|
volatile uint8_t* _MOSI_PORT;
|
||||||
|
volatile uint8_t* _SS_PORT;
|
||||||
|
volatile uint8_t* _SCK_PORT;
|
||||||
|
volatile uint8_t* _MISO_PIN;
|
||||||
|
byte _SS_HIGH;
|
||||||
|
byte _MOSI_HIGH;
|
||||||
|
byte _SCK_HIGH;
|
||||||
|
byte _SS_LOW;
|
||||||
|
byte _MOSI_LOW;
|
||||||
|
byte _SCK_LOW;
|
||||||
|
byte _MISO_MASK;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SoftSPIClass SPI;
|
||||||
|
|
||||||
|
#endif
|
266
hardware/digistump/avr/cores/pro/TinySoftwareSerial.cpp
Normal file
266
hardware/digistump/avr/cores/pro/TinySoftwareSerial.cpp
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
TinySoftwareSerial.cpp - Hardware serial library for Wiring
|
||||||
|
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 23 November 2006 by David A. Mellis
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
#if USE_SOFTWARE_SERIAL
|
||||||
|
#include "TinySoftwareSerial.h"
|
||||||
|
|
||||||
|
// Define constants and variables for buffering incoming serial data. We're
|
||||||
|
// using a ring buffer (I think), in which rx_buffer_head is the index of the
|
||||||
|
// location to which to write the next incoming character and rx_buffer_tail
|
||||||
|
// is the index of the location from which to read.
|
||||||
|
|
||||||
|
extern "C"{
|
||||||
|
uint8_t getch() {
|
||||||
|
uint8_t ch = 0;
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
" rcall uartDelay\n" // Get to 0.25 of start bit (our baud is too fast, so give room to correct)
|
||||||
|
"1: rcall uartDelay\n" // Wait 0.25 bit period
|
||||||
|
" rcall uartDelay\n" // Wait 0.25 bit period
|
||||||
|
" rcall uartDelay\n" // Wait 0.25 bit period
|
||||||
|
" rcall uartDelay\n" // Wait 0.25 bit period
|
||||||
|
" clc\n"
|
||||||
|
" in r23,%[pin]\n"
|
||||||
|
" and r23, %[mask]\n"
|
||||||
|
" breq 2f\n"
|
||||||
|
" sec\n"
|
||||||
|
"2: ror %0\n"
|
||||||
|
" dec %[count]\n"
|
||||||
|
" breq 3f\n"
|
||||||
|
" rjmp 1b\n"
|
||||||
|
"3: rcall uartDelay\n" // Wait 0.25 bit period
|
||||||
|
" rcall uartDelay\n" // Wait 0.25 bit period
|
||||||
|
:
|
||||||
|
"=r" (ch)
|
||||||
|
:
|
||||||
|
"0" ((uint8_t)0),
|
||||||
|
[count] "r" ((uint8_t)8),
|
||||||
|
[pin] "I" (_SFR_IO_ADDR(ANALOG_COMP_PIN)),
|
||||||
|
[mask] "r" (Serial._rxmask)
|
||||||
|
:
|
||||||
|
"r23",
|
||||||
|
"r24",
|
||||||
|
"r25"
|
||||||
|
);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartDelay() {
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"mov r25,%[count]\n"
|
||||||
|
"1:dec r25\n"
|
||||||
|
"brne 1b\n"
|
||||||
|
"ret\n"
|
||||||
|
::[count] "r" ((uint8_t)Serial._delayCount)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined (ANALOG_COMP_vect) && defined(ANA_COMP_vect)
|
||||||
|
//rename the vector so we can use it.
|
||||||
|
#define ANALOG_COMP_vect ANA_COMP_vect
|
||||||
|
#elif !defined (ANALOG_COMP_vect)
|
||||||
|
#error Tiny Software Serial cant find the Analog comparator interrupt vector!
|
||||||
|
#endif
|
||||||
|
ISR(ANALOG_COMP_vect){
|
||||||
|
char ch = getch(); //read in the character softwarily - I know its not a word, but it sounded cool, so you know what: #define softwarily 1
|
||||||
|
store_char(ch, Serial._rx_buffer);
|
||||||
|
sbi(ACSR,ACI); //clear the flag.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
soft_ring_buffer rx_buffer = { { 0 }, 0, 0 };
|
||||||
|
|
||||||
|
// Constructor ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TinySoftwareSerial::TinySoftwareSerial(soft_ring_buffer *rx_buffer, uint8_t txBit, uint8_t rxBit)
|
||||||
|
{
|
||||||
|
_rx_buffer = rx_buffer;
|
||||||
|
|
||||||
|
_rxmask = _BV(rxBit);
|
||||||
|
_txmask = _BV(txBit);
|
||||||
|
_txunmask = ~_txmask;
|
||||||
|
|
||||||
|
_delayCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void TinySoftwareSerial::begin(long baud)
|
||||||
|
{
|
||||||
|
long tempDelay = (((F_CPU/baud)-39)/12);
|
||||||
|
if ((tempDelay > 255) || (tempDelay <= 0)){
|
||||||
|
end(); //Cannot start as it would screw up uartDelay().
|
||||||
|
}
|
||||||
|
_delayCount = (uint8_t)tempDelay;
|
||||||
|
cbi(ACSR,ACIE); //turn off the comparator interrupt to allow change of ACD
|
||||||
|
#ifdef ACBG
|
||||||
|
sbi(ACSR,ACBG); //enable the internal bandgap reference - used instead of AIN0 to allow it to be used for TX.
|
||||||
|
#endif
|
||||||
|
cbi(ACSR,ACD); //turn on the comparator for RX
|
||||||
|
#ifdef ACIC
|
||||||
|
cbi(ACSR,ACIC); //prevent the comparator from affecting timer1 - just to be safe.
|
||||||
|
#endif
|
||||||
|
sbi(ACSR,ACIS1); //interrupt on rising edge (this means RX has gone from Mark state to Start bit state).
|
||||||
|
sbi(ACSR,ACIS0);
|
||||||
|
//Setup the pins in case someone messed with them.
|
||||||
|
ANALOG_COMP_DDR &= ~_rxmask; //set RX to an input
|
||||||
|
ANALOG_COMP_PORT |= _rxmask; //enable pullup on RX pin - to prevent accidental interrupt triggers.
|
||||||
|
ANALOG_COMP_DDR |= _txmask; //set TX to an output.
|
||||||
|
ANALOG_COMP_PORT |= _txmask; //set TX pin high
|
||||||
|
sbi(ACSR,ACI); //clear the flag.
|
||||||
|
sbi(ACSR,ACIE); //turn on the comparator interrupt to allow us to use it for RX
|
||||||
|
#ifdef ACSRB
|
||||||
|
ACSRB = 0; //Use AIN0 as +, AIN1 as -, no hysteresis - just like ones without this register.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TinySoftwareSerial::end()
|
||||||
|
{
|
||||||
|
sbi(ACSR,ACI); //clear the flag.
|
||||||
|
cbi(ACSR,ACIE); //turn off the comparator interrupt to allow change of ACD, and because it needs to be turned off now too!
|
||||||
|
#ifdef ACBG
|
||||||
|
cbi(ACSR,ACBG); //disable the bandgap reference
|
||||||
|
#endif
|
||||||
|
sbi(ACSR,ACD); //turn off the comparator to save power
|
||||||
|
_delayCount = 0;
|
||||||
|
_rx_buffer->head = _rx_buffer->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TinySoftwareSerial::available(void)
|
||||||
|
{
|
||||||
|
return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_char(unsigned char c, soft_ring_buffer *buffer)
|
||||||
|
{
|
||||||
|
int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
|
||||||
|
// if we should be storing the received character into the location
|
||||||
|
// just before the tail (meaning that the head would advance to the
|
||||||
|
// current location of the tail), we're about to overflow the buffer
|
||||||
|
// and so we don't write the character or advance the head.
|
||||||
|
if (i != buffer->tail) {
|
||||||
|
buffer->buffer[buffer->head] = c;
|
||||||
|
buffer->head = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TinySoftwareSerial::peek(void)
|
||||||
|
{
|
||||||
|
if (_rx_buffer->head == _rx_buffer->tail) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return _rx_buffer->buffer[_rx_buffer->tail];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TinySoftwareSerial::read(void)
|
||||||
|
{
|
||||||
|
// if the head isn't ahead of the tail, we don't have any characters
|
||||||
|
if (_rx_buffer->head == _rx_buffer->tail) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
|
||||||
|
_rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TinySoftwareSerial::write(uint8_t ch)
|
||||||
|
{
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli(); //Prevent interrupts from breaking the transmission. Note: TinySoftwareSerial is half duplex.
|
||||||
|
//it can either recieve or send, not both (because recieving requires an interrupt and would stall transmission
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
" com %[ch]\n" // ones complement, carry set
|
||||||
|
" sec\n"
|
||||||
|
"1: brcc 2f\n"
|
||||||
|
" in r23,%[uartPort] \n"
|
||||||
|
" and r23,%[uartUnmask]\n"
|
||||||
|
" out %[uartPort],r23 \n"
|
||||||
|
" rjmp 3f\n"
|
||||||
|
"2: in r23,%[uartPort] \n"
|
||||||
|
" or r23,%[uartMask]\n"
|
||||||
|
" out %[uartPort],r23 \n"
|
||||||
|
" nop\n"
|
||||||
|
"3: rcall uartDelay\n"
|
||||||
|
" rcall uartDelay\n"
|
||||||
|
" rcall uartDelay\n"
|
||||||
|
" rcall uartDelay\n"
|
||||||
|
" lsr %[ch]\n"
|
||||||
|
" dec %[count]\n"
|
||||||
|
" brne 1b\n"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[ch] "r" (ch),
|
||||||
|
[count] "r" ((uint8_t)10),
|
||||||
|
[uartPort] "I" (_SFR_IO_ADDR(ANALOG_COMP_PORT)),
|
||||||
|
[uartMask] "r" (_txmask),
|
||||||
|
[uartUnmask] "r" (_txunmask)
|
||||||
|
: "r23",
|
||||||
|
"r24",
|
||||||
|
"r25"
|
||||||
|
);
|
||||||
|
SREG = oldSREG;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TinySoftwareSerial::flush()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TinySoftwareSerial::operator bool() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||||
|
#ifndef ANALOG_COMP_DDR
|
||||||
|
#error Please define ANALOG_COMP_DDR in the pins_arduino.h file!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ANALOG_COMP_PORT
|
||||||
|
#error Please define ANALOG_COMP_PORT in the pins_arduino.h file!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ANALOG_COMP_PIN
|
||||||
|
#error Please define ANALOG_COMP_PIN in the pins_arduino.h file!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ANALOG_COMP_AIN0_BIT
|
||||||
|
#error Please define ANALOG_COMP_AIN0_BIT in the pins_arduino.h file!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ANALOG_COMP_AIN1_BIT
|
||||||
|
#error Please define ANALOG_COMP_AIN1_BIT in the pins_arduino.h file!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TinySoftwareSerial Serial(&rx_buffer, ANALOG_COMP_AIN0_BIT, ANALOG_COMP_AIN1_BIT);
|
||||||
|
|
||||||
|
#endif // whole file
|
61
hardware/digistump/avr/cores/pro/TinySoftwareSerial.h
Normal file
61
hardware/digistump/avr/cores/pro/TinySoftwareSerial.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
#if USE_SOFTWARE_SERIAL
|
||||||
|
#ifndef TinySoftwareSerial_h
|
||||||
|
#define TinySoftwareSerial_h
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
#if !defined(ACSR) && defined(ACSRA)
|
||||||
|
#define ACSR ACSRA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (RAMEND < 250)
|
||||||
|
#define SERIAL_BUFFER_SIZE 8
|
||||||
|
#elif (RAMEND < 500)
|
||||||
|
#define SERIAL_BUFFER_SIZE 16
|
||||||
|
#elif (RAMEND < 1000)
|
||||||
|
#define SERIAL_BUFFER_SIZE 32
|
||||||
|
#else
|
||||||
|
#define SERIAL_BUFFER_SIZE 128
|
||||||
|
#endif
|
||||||
|
struct soft_ring_buffer
|
||||||
|
{
|
||||||
|
unsigned char buffer[SERIAL_BUFFER_SIZE];
|
||||||
|
int head;
|
||||||
|
int tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C"{
|
||||||
|
void uartDelay() __attribute__ ((naked));
|
||||||
|
uint8_t getch();
|
||||||
|
void store_char(unsigned char c, soft_ring_buffer *buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TinySoftwareSerial : public Stream
|
||||||
|
{
|
||||||
|
public: //should be private but needed by extern "C" {} functions.
|
||||||
|
uint8_t _rxmask;
|
||||||
|
uint8_t _txmask;
|
||||||
|
uint8_t _txunmask;
|
||||||
|
soft_ring_buffer *_rx_buffer;
|
||||||
|
uint8_t _delayCount;
|
||||||
|
public:
|
||||||
|
TinySoftwareSerial(soft_ring_buffer *rx_buffer, uint8_t txBit, uint8_t rxBit);
|
||||||
|
void begin(long);
|
||||||
|
void end();
|
||||||
|
virtual int available(void);
|
||||||
|
virtual int peek(void);
|
||||||
|
virtual int read(void);
|
||||||
|
virtual void flush(void);
|
||||||
|
virtual size_t write(uint8_t);
|
||||||
|
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||||
|
operator bool();
|
||||||
|
};
|
||||||
|
|
||||||
|
#if (!defined(UBRRH) && !defined(UBRR0H)) || USE_SOFTWARE_SERIAL
|
||||||
|
extern TinySoftwareSerial Serial;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//extern void putch(uint8_t);
|
||||||
|
#endif
|
||||||
|
#endif
|
546
hardware/digistump/avr/cores/pro/Tone.cpp
Normal file
546
hardware/digistump/avr/cores/pro/Tone.cpp
Normal file
@ -0,0 +1,546 @@
|
|||||||
|
/* Tone.cpp
|
||||||
|
|
||||||
|
A Tone Generator Library
|
||||||
|
|
||||||
|
Written by Brett Hagman
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Version Modified By Date Comments
|
||||||
|
------- ----------- -------- --------
|
||||||
|
0001 B Hagman 09/08/02 Initial coding
|
||||||
|
0002 B Hagman 09/08/18 Multiple pins
|
||||||
|
0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
|
||||||
|
0004 B Hagman 09/09/26 Fixed problems with ATmega8
|
||||||
|
0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
|
||||||
|
09/11/25 Changed pin toggle method to XOR
|
||||||
|
09/11/25 Fixed timer0 from being excluded
|
||||||
|
0006 D Mellis 09/12/29 Replaced objects with functions
|
||||||
|
0007 B Cook 10/05/03 Rewritten to only work with Timer1 and support direct hardware output
|
||||||
|
0008 B Cook 10/05/03 Rewritten so the timer can be selected at compile time
|
||||||
|
0009 T Carpenter 12/08/06 Rewritten to remove requirement for all the wierd timer name creation macros.
|
||||||
|
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
// timerx_toggle_count:
|
||||||
|
// > 0 - duration specified
|
||||||
|
// = 0 - stopped
|
||||||
|
// < 0 - infinitely (until stop() method called, or new play() called)
|
||||||
|
|
||||||
|
static volatile long tone_timer_toggle_count;
|
||||||
|
static volatile uint8_t *tone_timer_pin_register;
|
||||||
|
static volatile uint8_t tone_timer_pin_mask;
|
||||||
|
|
||||||
|
static uint8_t tone_pin = 255;
|
||||||
|
|
||||||
|
|
||||||
|
void tone( uint8_t _pin, unsigned int frequency, unsigned long duration )
|
||||||
|
{
|
||||||
|
if ( tone_pin == 255 )
|
||||||
|
{
|
||||||
|
/* Set the timer to power-up conditions so we start from a known state */
|
||||||
|
// Ensure the timer is in the same state as power-up
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
TCCR0B = (0<<FOC0A) | (0<<FOC0B) | (0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
|
||||||
|
TCCR0A = (0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT0 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR0A = 0;
|
||||||
|
OCR0B = 0;
|
||||||
|
#if defined(TIMSK)
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#elif defined(TIMSK1)
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR0 |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
|
||||||
|
// Turn off Clear on Compare Match, turn off PWM A, disconnect the timer from the output pin, stop the clock
|
||||||
|
TCCR1 = (0<<CTC1) | (0<<PWM1A) | (0<<COM1A1) | (0<<COM1A0) | (0<<CS13) | (0<<CS12) | (0<<CS11) | (0<<CS10);
|
||||||
|
// Turn off PWM A, disconnect the timer from the output pin, no Force Output Compare Match, no Prescaler Reset
|
||||||
|
GTCCR &= ~((1<<PWM1B) | (1<<COM1B1) | (1<<COM1B0) | (1<<FOC1B) | (1<<FOC1A) | (1<<PSR1));
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
OCR1C = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK &= ~((1<<OCIE1A) | (1<<OCIE1B) | (1<<TOIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<OCF1A) | (1<<OCF1B) | (1<<TOV1));
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
|
||||||
|
TCCR1A = 0;
|
||||||
|
TCCR1B = 0;
|
||||||
|
TCCR1C = 0;
|
||||||
|
TCCR1D = 0;
|
||||||
|
TCCR1E = 0;
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<OCIE1D));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<OCF1D));
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
// Turn off Input Capture Noise Canceler, Input Capture Edge Select on Falling, stop the clock
|
||||||
|
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
|
||||||
|
// Disconnect the timer from the output pins, Set Waveform Generation Mode to Normal
|
||||||
|
TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
#if defined(TIMSK)
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
|
||||||
|
#elif defined(TIMSK1)
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK1 &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR1 |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compare Output Mode = Normal port operation, OCxA/OCxB disconnected.
|
||||||
|
Waveform Generation Mode = 4; 0100; CTC; (Clear Timer on Compare); OCR1A; Immediate; MAX
|
||||||
|
Clock Select = No clock source (Timer/Counter stopped).
|
||||||
|
Note: Turn off the clock first to avoid ticks and scratches.
|
||||||
|
*/
|
||||||
|
#if TIMER_TO_USE_FOR_TONE == 1
|
||||||
|
#if defined(TCCR1)
|
||||||
|
sbi(TCCR1,CTC1);
|
||||||
|
cbi(TCCR1,PWM1A);
|
||||||
|
cbi(GTCCR,PWM1B);
|
||||||
|
#elif !defined(TCCR1E)
|
||||||
|
cbi(TCCR1A,WGM10);
|
||||||
|
cbi(TCCR1A,WGM11);
|
||||||
|
sbi(TCCR1B,WGM12);
|
||||||
|
cbi(TCCR1B,WGM13);
|
||||||
|
#endif
|
||||||
|
#elif TIMER_TO_USE_FOR_TONE == 0
|
||||||
|
cbi(TCCR0A,WGM00);
|
||||||
|
sbi(TCCR0A,WGM01);
|
||||||
|
cbi(TCCR0B,WGM02);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the tone pin can be driven directly from the timer */
|
||||||
|
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
|
||||||
|
if ( (digitalPinToTimer(_pin) == TIMER1A) || (digitalPinToTimer(_pin) == TIMER1B) || (digitalPinToTimer(_pin) == TIMER1D) )
|
||||||
|
{
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
if ( (digitalPinToTimer(_pin) == TIMER1A) || (digitalPinToTimer(_pin) == TIMER1B) )
|
||||||
|
{
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
if ( (digitalPinToTimer(_pin) == TIMER0A) || (digitalPinToTimer(_pin) == TIMER0B) )
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
if (0)
|
||||||
|
{ //unsupported, so only use software.
|
||||||
|
#endif
|
||||||
|
/* Pin toggling is handled by the hardware */
|
||||||
|
tone_timer_pin_register = NULL;
|
||||||
|
tone_timer_pin_mask = 0;
|
||||||
|
uint8_t timer = digitalPinToTimer(_pin);
|
||||||
|
#if defined(COM0A1)
|
||||||
|
//Just in case there are now pwm pins on timer0 (ATTiny861)
|
||||||
|
if (timer == TIMER0A)
|
||||||
|
{
|
||||||
|
/* Compare Output Mode = Toggle OC0A on Compare Match. */
|
||||||
|
cbi(TCCR0A,COM0A1);
|
||||||
|
sbi(TCCR0A,COM0A0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (timer == TIMER1A)
|
||||||
|
{
|
||||||
|
/* Compare Output Mode = Toggle OC1A on Compare Match. */
|
||||||
|
#if defined(TCCR1)
|
||||||
|
cbi(TCCR1,COM1A1);
|
||||||
|
sbi(TCCR1,COM1A0);
|
||||||
|
#elif defined(TCCR1E)
|
||||||
|
cbi(TCCR1C,COM1A1S);
|
||||||
|
sbi(TCCR1C,COM1A0S);
|
||||||
|
#else
|
||||||
|
cbi(TCCR1A,COM1A1);
|
||||||
|
sbi(TCCR1A,COM1A0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if defined(COM0B1)
|
||||||
|
//Just in case there are <2 pwm pins on timer0 (ATTiny861)
|
||||||
|
else if (timer == TIMER0B)
|
||||||
|
{
|
||||||
|
/* Compare Output Mode = Toggle OC0B on Compare Match. */
|
||||||
|
cbi(TCCR0A,COM0B1);
|
||||||
|
sbi(TCCR0A,COM0B0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(COM1D1)
|
||||||
|
//in case there is a OCRD. (ATtiny861)
|
||||||
|
else if (timer == TIMER1D){
|
||||||
|
/* Compare Output Mode = Toggle OC1D on Compare Match. */
|
||||||
|
#if defined(TCCR1)
|
||||||
|
cbi(TCCR1,COM1D1);
|
||||||
|
sbi(TCCR1,COM1D0);
|
||||||
|
#elif defined(TCCR1E)
|
||||||
|
cbi(TCCR1C,COM1D1);
|
||||||
|
sbi(TCCR1C,COM1D0);
|
||||||
|
#else
|
||||||
|
cbi(TCCR1A,COM1D1);
|
||||||
|
sbi(TCCR1A,COM1D0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Compare Output Mode = Toggle OC1B on Compare Match. */
|
||||||
|
#if defined(TCCR1)
|
||||||
|
cbi(GTCCR,COM1B1);
|
||||||
|
sbi(GTCCR,COM1B0);
|
||||||
|
#elif defined(TCCR1E)
|
||||||
|
cbi(TCCR1C,COM1B1S);
|
||||||
|
sbi(TCCR1C,COM1B0S);
|
||||||
|
#else
|
||||||
|
cbi(TCCR1A,COM1B1);
|
||||||
|
sbi(TCCR1A,COM1B0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Save information needed by the interrupt service routine */
|
||||||
|
tone_timer_pin_register = portOutputRegister( digitalPinToPort( _pin ) );
|
||||||
|
tone_timer_pin_mask = digitalPinToBitMask( _pin );
|
||||||
|
|
||||||
|
/* Compare Output Mode = Normal port operation, OCxA disconnected. */
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
TCCR0A &= ~((1<<COM0A1)|(1<<COM0A0)|(1<<COM0B1)|(1<<COM0B0));
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) & defined(TCCR1)
|
||||||
|
TCCR1 &= ~((1<<COM1A1)|(1<<COM1A0));
|
||||||
|
GTCCR &= ~((1<<COM1B1)|(1<<COM1B0));
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
|
||||||
|
TCCR1C &= ~((1<<COM1A1S)|(1<<COM1A0S)|(1<<COM1B1S)|(1<<COM1B0S)|(1<<COM1D1)|(1<<COM1D0));
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
TCCR1A &= ~((1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the pin is configured for output */
|
||||||
|
pinMode( _pin, OUTPUT );
|
||||||
|
|
||||||
|
tone_pin = _pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( tone_pin == _pin )
|
||||||
|
{
|
||||||
|
/* Stop the clock while we make changes, then set the counter to zero to reduce ticks and scratches. */
|
||||||
|
|
||||||
|
// Millis timer is always processor clock divided by MillisTimer_Prescale_Value (64)
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
TCCR0B &= ~((1<<CS02)|(1<<CS01)|(1<<CS00));
|
||||||
|
TCNT0 = 0;
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
|
||||||
|
TCCR1 &= ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10));
|
||||||
|
TCNT1 = 0;
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
|
||||||
|
TCCR1B &= ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10));
|
||||||
|
TCNT1 = 0;
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10));
|
||||||
|
TCNT1 = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( frequency > 0 )
|
||||||
|
{
|
||||||
|
/* Determine which prescaler to use */
|
||||||
|
/* Set the Output Compare Register (rounding up) */
|
||||||
|
|
||||||
|
#if TIMER_TO_USE_FOR_TONE == 1
|
||||||
|
uint16_t ocr = F_CPU / frequency / 2;
|
||||||
|
#if defined(TCCR1E)
|
||||||
|
uint8_t prescalarbits = 0b0001;
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
ocr >>= 3; //divide by 8
|
||||||
|
prescalarbits = 0b0100; // ck/8
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
ocr >>= 3; //divide by a further 8
|
||||||
|
prescalarbits = 0b0111; //ck/64
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
ocr >>= 2; //divide by a further 4
|
||||||
|
prescalarbits = 0b1001; //ck/256
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
// can't do any better than /1024
|
||||||
|
ocr >>= 2; //divide by a further 4
|
||||||
|
prescalarbits = 0b1011; //ck/1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#if defined(TCCR1)
|
||||||
|
uint8_t prescalarbits = 0b0001;
|
||||||
|
#else
|
||||||
|
uint8_t prescalarbits = 0b001;
|
||||||
|
#endif
|
||||||
|
if (ocr > 0xffff)
|
||||||
|
{
|
||||||
|
ocr /= 64;
|
||||||
|
#if defined(TCCR1)
|
||||||
|
prescalarbits = 0b0111;
|
||||||
|
#else
|
||||||
|
prescalarbits = 0b011;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ocr -= 1; //Note we are doing the subtraction of 1 here to save repeatedly calculating ocr from just the frequency in the if tree above
|
||||||
|
OCR1A = ocr;
|
||||||
|
|
||||||
|
#elif TIMER_TO_USE_FOR_TONE == 0
|
||||||
|
uint16_t ocr = F_CPU / frequency / 2;
|
||||||
|
uint8_t prescalarbits = 0b001; // ck/1
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
ocr >>= 3; //divide by 8
|
||||||
|
prescalarbits = 0b010; // ck/8
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
ocr >>= 3; //divide by a further 8
|
||||||
|
prescalarbits = 0b011; //ck/64
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
ocr >>= 2; //divide by a further 4
|
||||||
|
prescalarbits = 0b100; //ck/256
|
||||||
|
if (ocr > 256)
|
||||||
|
{
|
||||||
|
// can't do any better than /1024
|
||||||
|
ocr >>= 2; //divide by a further 4
|
||||||
|
prescalarbits = 0b101; //ck/1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ocr -= 1; //Note we are doing the subtraction of 1 here to save repeatedly calculating ocr from just the frequency in the if tree above
|
||||||
|
OCR0A = ocr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Does the caller want a specific duration? */
|
||||||
|
if ( duration > 0 )
|
||||||
|
{
|
||||||
|
/* Determine how many times the value toggles */
|
||||||
|
tone_timer_toggle_count = (2 * frequency * duration) / 1000;
|
||||||
|
/* Output Compare A Match Interrupt Enable */
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK |= (1<<OCIE1A);
|
||||||
|
#else
|
||||||
|
TIMSK1 |= (1<<OCIE1A);
|
||||||
|
#endif
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK |= (1<<OCIE0A);
|
||||||
|
#else
|
||||||
|
TIMSK0 |= (1<<OCIE0A);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Indicate to the interrupt service routine that we'll be running until further notice */
|
||||||
|
tone_timer_toggle_count = -1;
|
||||||
|
|
||||||
|
/* All pins but the OCxA / OCxB pins have to be driven by software */
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
#if defined(TCCR1E)
|
||||||
|
if ( (digitalPinToTimer(_pin) != TIMER1A) && (digitalPinToTimer(_pin) != TIMER1B) && (digitalPinToTimer(_pin) != TIMER1D) )
|
||||||
|
#else
|
||||||
|
if ( (digitalPinToTimer(_pin) != TIMER1A) && (digitalPinToTimer(_pin) != TIMER1B) )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Output Compare A Match Interrupt Enable (software control)*/
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK |= (1<<OCIE1A);
|
||||||
|
#else
|
||||||
|
TIMSK1 |= (1<<OCIE1A);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
if ( (digitalPinToTimer(_pin) != TIMER0A) && (digitalPinToTimer(_pin) != TIMER0B) )
|
||||||
|
{
|
||||||
|
/* Output Compare A Match Interrupt Enable (software control)*/
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK |= (1<<OCIE0A);
|
||||||
|
#else
|
||||||
|
TIMSK0 |= (1<<OCIE0A);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//Clock is always stopped before this point, which means all of CS[0..2] are already 0, so can just use a bitwise OR to set required bits
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
TCCR0B |= (prescalarbits << CS00);
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
|
||||||
|
TCCR1 |= (prescalarbits << CS10);
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
TCCR1B |= (prescalarbits << CS10);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* To be on the safe side, turn off all interrupts */
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK |= (1<<OCIE1A);
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B));
|
||||||
|
#if defined(ICIE1)
|
||||||
|
TIMSK &= ~(1<<ICIE1);
|
||||||
|
#endif
|
||||||
|
#if defined(OCIE1D)
|
||||||
|
TIMSK &= ~(1<<OCIE1D);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
TIMSK1 |= (1<<OCIE1A);
|
||||||
|
TIMSK1 &= ~((1<<ICIE1) | (1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1));
|
||||||
|
#endif
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK |= (1<<OCIE0A);
|
||||||
|
TIMSK &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
#else
|
||||||
|
TIMSK0 |= (1<<OCIE0A);
|
||||||
|
TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Clock is stopped. Counter is zero. The only thing left to do is turn off the output. */
|
||||||
|
digitalWrite( _pin, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void noTone( uint8_t _pin )
|
||||||
|
{
|
||||||
|
if ( (tone_pin != 255)
|
||||||
|
&& ((tone_pin == _pin) || (_pin == 255)) )
|
||||||
|
{
|
||||||
|
// Turn off all interrupts
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B));
|
||||||
|
#if defined(ICIE1)
|
||||||
|
TIMSK &= ~(1<<ICIE1);
|
||||||
|
#endif
|
||||||
|
#if defined(OCIE1D)
|
||||||
|
TIMSK &= ~(1<<OCIE1D);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
TIMSK1 &= ~((1<<ICIE1) | (1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1));
|
||||||
|
#endif
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
#if defined (TIMSK)
|
||||||
|
TIMSK &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
#else
|
||||||
|
TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// This just disables the tone. It doesn't reinitialise the PWM modules.
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
TCCR0B &= ~((1<<CS02) | (1<<CS01) | (1<<CS00)); //stop the clock
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
|
||||||
|
TCCR1 &= ~((1<<CS13) | (1<<CS12) | (1<<CS11) | (1<<CS10)); //stop the clock
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
|
||||||
|
TCCR1B &= ~((1<<CS13) | (1<<CS12) | (1<<CS11) | (1<<CS10)); //stop the clock
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
TCCR1B &= ~((1<<CS12) | (1<<CS11) | (1<<CS10)); //stop the clock
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set the output low
|
||||||
|
if ( tone_timer_pin_register != NULL )
|
||||||
|
{
|
||||||
|
*tone_timer_pin_register &= ~(tone_timer_pin_mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
digitalWrite( tone_pin, LOW );
|
||||||
|
}
|
||||||
|
|
||||||
|
tone_pin = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
ISR(TIMER0_COMPA_vect)
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
ISR(TIMER1_COMPA_vect)
|
||||||
|
#else
|
||||||
|
#error Tone timer Overflow vector not defined!
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if ( tone_timer_toggle_count != 0 )
|
||||||
|
{
|
||||||
|
if ( tone_timer_toggle_count > 0 )
|
||||||
|
{
|
||||||
|
--tone_timer_toggle_count;
|
||||||
|
|
||||||
|
if ( tone_timer_toggle_count == 0 )
|
||||||
|
{
|
||||||
|
// Shutdown the hardware
|
||||||
|
noTone( 255 );
|
||||||
|
|
||||||
|
// Skip the rest. We're finished.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*tone_timer_pin_register ^= tone_timer_pin_mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Shutdown the hardware
|
||||||
|
noTone( 255 );
|
||||||
|
}
|
||||||
|
}
|
168
hardware/digistump/avr/cores/pro/WCharacter.h
Normal file
168
hardware/digistump/avr/cores/pro/WCharacter.h
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
WCharacter.h - Character utility functions for Wiring & Arduino
|
||||||
|
Copyright (c) 2010 Hernando Barragan. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Character_h
|
||||||
|
#define Character_h
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
// WCharacter.h prototypes
|
||||||
|
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isAlpha(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isAscii(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isWhitespace(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isControl(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isDigit(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isGraph(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isLowerCase(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isPrintable(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isPunct(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isSpace(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isUpperCase(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||||
|
inline int toAscii(int c) __attribute__((always_inline));
|
||||||
|
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||||
|
inline int toUpperCase(int c)__attribute__((always_inline));
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an alphanumeric character.
|
||||||
|
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||||
|
inline boolean isAlphaNumeric(int c)
|
||||||
|
{
|
||||||
|
return ( isalnum(c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an alphabetic character.
|
||||||
|
// It is equivalent to (isupper(c) || islower(c)).
|
||||||
|
inline boolean isAlpha(int c)
|
||||||
|
{
|
||||||
|
return ( isalpha(c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks whether c is a 7-bit unsigned char value
|
||||||
|
// that fits into the ASCII character set.
|
||||||
|
inline boolean isAscii(int c)
|
||||||
|
{
|
||||||
|
return ( isascii (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a blank character, that is, a space or a tab.
|
||||||
|
inline boolean isWhitespace(int c)
|
||||||
|
{
|
||||||
|
return ( isblank (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a control character.
|
||||||
|
inline boolean isControl(int c)
|
||||||
|
{
|
||||||
|
return ( iscntrl (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a digit (0 through 9).
|
||||||
|
inline boolean isDigit(int c)
|
||||||
|
{
|
||||||
|
return ( isdigit (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character except space.
|
||||||
|
inline boolean isGraph(int c)
|
||||||
|
{
|
||||||
|
return ( isgraph (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a lower-case character.
|
||||||
|
inline boolean isLowerCase(int c)
|
||||||
|
{
|
||||||
|
return (islower (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character including space.
|
||||||
|
inline boolean isPrintable(int c)
|
||||||
|
{
|
||||||
|
return ( isprint (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character which is not a space
|
||||||
|
// or an alphanumeric character.
|
||||||
|
inline boolean isPunct(int c)
|
||||||
|
{
|
||||||
|
return ( ispunct (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for white-space characters. For the avr-libc library,
|
||||||
|
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||||
|
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||||
|
inline boolean isSpace(int c)
|
||||||
|
{
|
||||||
|
return ( isspace (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an uppercase letter.
|
||||||
|
inline boolean isUpperCase(int c)
|
||||||
|
{
|
||||||
|
return ( isupper (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||||
|
// 8 9 a b c d e f A B C D E F.
|
||||||
|
inline boolean isHexadecimalDigit(int c)
|
||||||
|
{
|
||||||
|
return ( isxdigit (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts c to a 7-bit unsigned char value that fits into the
|
||||||
|
// ASCII character set, by clearing the high-order bits.
|
||||||
|
inline int toAscii(int c)
|
||||||
|
{
|
||||||
|
return toascii (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Warning:
|
||||||
|
// Many people will be unhappy if you use this function.
|
||||||
|
// This function will convert accented letters into random
|
||||||
|
// characters.
|
||||||
|
|
||||||
|
// Converts the letter c to lower case, if possible.
|
||||||
|
inline int toLowerCase(int c)
|
||||||
|
{
|
||||||
|
return tolower (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts the letter c to upper case, if possible.
|
||||||
|
inline int toUpperCase(int c)
|
||||||
|
{
|
||||||
|
return toupper (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
155
hardware/digistump/avr/cores/pro/WInterrupts.c
Normal file
155
hardware/digistump/avr/cores/pro/WInterrupts.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Wiring project - http://wiring.uniandes.edu.co
|
||||||
|
|
||||||
|
Copyright (c) 2004-05 Hernando Barragan
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Modified 24 November 2006 by David A. Mellis
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 09-10-2009 for attiny45 A.Saporetti
|
||||||
|
Modified 20-11-2010 - B.Cook - Correct a minor bug in attachInterrupt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
volatile static voidFuncPtr intFunc[NUMBER_EXTERNAL_INTERRUPTS];
|
||||||
|
|
||||||
|
#if defined( MCUCR ) && ! defined( EICRA )
|
||||||
|
#define EICRA MCUCR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( GIMSK ) && ! defined( EIMSK )
|
||||||
|
#define EIMSK GIMSK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
|
||||||
|
{
|
||||||
|
if ( interruptNum < NUMBER_EXTERNAL_INTERRUPTS )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If attachInterrupt is called in succession for the same
|
||||||
|
interruptNum but a different userFunc then the following line
|
||||||
|
is not safe. Changing intFunc is not atomic.
|
||||||
|
intFunc[interruptNum] = userFunc;
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
// save interrupt flag
|
||||||
|
uint8_t SaveSREG = SREG;
|
||||||
|
// disable interrupts
|
||||||
|
cli();
|
||||||
|
// access the shared data
|
||||||
|
intFunc[interruptNum] = userFunc;
|
||||||
|
// restore the interrupt flag
|
||||||
|
SREG = SaveSREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the interrupt mode (trigger on low input, any change, rising
|
||||||
|
// edge, or falling edge). The mode constants were chosen to correspond
|
||||||
|
// to the configuration bits in the hardware register, so we simply shift
|
||||||
|
// the mode into place.
|
||||||
|
|
||||||
|
// Enable the interrupt.
|
||||||
|
|
||||||
|
switch ( interruptNum )
|
||||||
|
{
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
case EXTERNAL_INTERRUPT_0:
|
||||||
|
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
|
||||||
|
EIMSK |= (1 << INT0);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2 && !defined(ISC11)
|
||||||
|
//For ATtiny861, but interrupts share the same vector.
|
||||||
|
case EXTERNAL_INTERRUPT_1:
|
||||||
|
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
|
||||||
|
EIMSK |= (1 << INT1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2 && defined(ISC11)
|
||||||
|
case EXTERNAL_INTERRUPT_1:
|
||||||
|
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
|
||||||
|
EIMSK |= (1 << INT1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS > 2
|
||||||
|
#error Add handlers for the additional interrupts.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void detachInterrupt(uint8_t interruptNum)
|
||||||
|
{
|
||||||
|
if ( interruptNum < NUMBER_EXTERNAL_INTERRUPTS )
|
||||||
|
{
|
||||||
|
// Disable the interrupt. (We can't assume that interruptNum is equal
|
||||||
|
// to the number of the EIMSK bit to clear, as this isn't true on the
|
||||||
|
// ATmega8. There, INT0 is 6 and INT1 is 7.)
|
||||||
|
|
||||||
|
switch (interruptNum)
|
||||||
|
{
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
case EXTERNAL_INTERRUPT_0:
|
||||||
|
EIMSK &= ~(1 << INT0);
|
||||||
|
break;;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2
|
||||||
|
case EXTERNAL_INTERRUPT_1:
|
||||||
|
EIMSK &= ~(1 << INT1);
|
||||||
|
break;;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS > 2
|
||||||
|
#error Add handlers for the additional interrupts.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
intFunc[interruptNum] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
ISR(EXTERNAL_INTERRUPT_0_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[EXTERNAL_INTERRUPT_0])
|
||||||
|
intFunc[EXTERNAL_INTERRUPT_0]();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2
|
||||||
|
ISR(EXTERNAL_INTERRUPT_1_vect)
|
||||||
|
{
|
||||||
|
if(intFunc[EXTERNAL_INTERRUPT_1])
|
||||||
|
intFunc[EXTERNAL_INTERRUPT_1]();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS > 2
|
||||||
|
#error Add handlers for the additional interrupts.
|
||||||
|
#endif
|
60
hardware/digistump/avr/cores/pro/WMath.cpp
Normal file
60
hardware/digistump/avr/cores/pro/WMath.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Wiring project - http://wiring.org.co
|
||||||
|
Copyright (c) 2004-06 Hernando Barragan
|
||||||
|
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "stdlib.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void randomSeed(unsigned int seed)
|
||||||
|
{
|
||||||
|
if (seed != 0) {
|
||||||
|
srandom(seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long random(long howbig)
|
||||||
|
{
|
||||||
|
if (howbig == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return random() % howbig;
|
||||||
|
}
|
||||||
|
|
||||||
|
long random(long howsmall, long howbig)
|
||||||
|
{
|
||||||
|
if (howsmall >= howbig) {
|
||||||
|
return howsmall;
|
||||||
|
}
|
||||||
|
long diff = howbig - howsmall;
|
||||||
|
return random(diff) + howsmall;
|
||||||
|
}
|
||||||
|
|
||||||
|
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||||
|
{
|
||||||
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int makeWord(unsigned int w) { return w; }
|
||||||
|
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }
|
2
hardware/digistump/avr/cores/pro/WProgram.h
Normal file
2
hardware/digistump/avr/cores/pro/WProgram.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
//For compatibility with older programs
|
||||||
|
#include "Arduino.h"
|
744
hardware/digistump/avr/cores/pro/WString.cpp
Normal file
744
hardware/digistump/avr/cores/pro/WString.cpp
Normal file
@ -0,0 +1,744 @@
|
|||||||
|
/*
|
||||||
|
WString.cpp - String library for Wiring & Arduino
|
||||||
|
...mostly rewritten by Paul Stoffregen...
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||||
|
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WString.h"
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Constructors */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
String::String(const char *cstr)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
if (cstr) copy(cstr, strlen(cstr));
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(const String &value)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
*this = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(const __FlashStringHelper *pstr)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
*this = pstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String::String(String &&rval)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
move(rval);
|
||||||
|
}
|
||||||
|
String::String(StringSumHelper &&rval)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
move(rval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String::String(char c)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[2];
|
||||||
|
buf[0] = c;
|
||||||
|
buf[1] = 0;
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned char value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned char)];
|
||||||
|
utoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(int value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[2 + 8 * sizeof(int)];
|
||||||
|
itoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned int value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned int)];
|
||||||
|
utoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(long value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[2 + 8 * sizeof(long)];
|
||||||
|
ltoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(unsigned long value, unsigned char base)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[1 + 8 * sizeof(unsigned long)];
|
||||||
|
ultoa(value, buf, base);
|
||||||
|
*this = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(float value, unsigned char decimalPlaces)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[33];
|
||||||
|
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String(double value, unsigned char decimalPlaces)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
char buf[33];
|
||||||
|
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::~String()
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Memory Management */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
inline void String::init(void)
|
||||||
|
{
|
||||||
|
buffer = NULL;
|
||||||
|
capacity = 0;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::invalidate(void)
|
||||||
|
{
|
||||||
|
if (buffer) free(buffer);
|
||||||
|
buffer = NULL;
|
||||||
|
capacity = len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::reserve(unsigned int size)
|
||||||
|
{
|
||||||
|
if (buffer && capacity >= size) return 1;
|
||||||
|
if (changeBuffer(size)) {
|
||||||
|
if (len == 0) buffer[0] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::changeBuffer(unsigned int maxStrLen)
|
||||||
|
{
|
||||||
|
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
|
||||||
|
if (newbuffer) {
|
||||||
|
buffer = newbuffer;
|
||||||
|
capacity = maxStrLen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Copy and Move */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
String & String::copy(const char *cstr, unsigned int length)
|
||||||
|
{
|
||||||
|
if (!reserve(length)) {
|
||||||
|
invalidate();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
len = length;
|
||||||
|
strcpy(buffer, cstr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
|
||||||
|
{
|
||||||
|
if (!reserve(length)) {
|
||||||
|
invalidate();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
len = length;
|
||||||
|
strcpy_P(buffer, (PGM_P)pstr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
void String::move(String &rhs)
|
||||||
|
{
|
||||||
|
if (buffer) {
|
||||||
|
if (capacity >= rhs.len) {
|
||||||
|
strcpy(buffer, rhs.buffer);
|
||||||
|
len = rhs.len;
|
||||||
|
rhs.len = 0;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer = rhs.buffer;
|
||||||
|
capacity = rhs.capacity;
|
||||||
|
len = rhs.len;
|
||||||
|
rhs.buffer = NULL;
|
||||||
|
rhs.capacity = 0;
|
||||||
|
rhs.len = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String & String::operator = (const String &rhs)
|
||||||
|
{
|
||||||
|
if (this == &rhs) return *this;
|
||||||
|
|
||||||
|
if (rhs.buffer) copy(rhs.buffer, rhs.len);
|
||||||
|
else invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String & String::operator = (String &&rval)
|
||||||
|
{
|
||||||
|
if (this != &rval) move(rval);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::operator = (StringSumHelper &&rval)
|
||||||
|
{
|
||||||
|
if (this != &rval) move(rval);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String & String::operator = (const char *cstr)
|
||||||
|
{
|
||||||
|
if (cstr) copy(cstr, strlen(cstr));
|
||||||
|
else invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & String::operator = (const __FlashStringHelper *pstr)
|
||||||
|
{
|
||||||
|
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
||||||
|
else invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* concat */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
unsigned char String::concat(const String &s)
|
||||||
|
{
|
||||||
|
return concat(s.buffer, s.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const char *cstr, unsigned int length)
|
||||||
|
{
|
||||||
|
unsigned int newlen = len + length;
|
||||||
|
if (!cstr) return 0;
|
||||||
|
if (length == 0) return 1;
|
||||||
|
if (!reserve(newlen)) return 0;
|
||||||
|
strcpy(buffer + len, cstr);
|
||||||
|
len = newlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const char *cstr)
|
||||||
|
{
|
||||||
|
if (!cstr) return 0;
|
||||||
|
return concat(cstr, strlen(cstr));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(char c)
|
||||||
|
{
|
||||||
|
char buf[2];
|
||||||
|
buf[0] = c;
|
||||||
|
buf[1] = 0;
|
||||||
|
return concat(buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned char num)
|
||||||
|
{
|
||||||
|
char buf[1 + 3 * sizeof(unsigned char)];
|
||||||
|
itoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(int num)
|
||||||
|
{
|
||||||
|
char buf[2 + 3 * sizeof(int)];
|
||||||
|
itoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned int num)
|
||||||
|
{
|
||||||
|
char buf[1 + 3 * sizeof(unsigned int)];
|
||||||
|
utoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(long num)
|
||||||
|
{
|
||||||
|
char buf[2 + 3 * sizeof(long)];
|
||||||
|
ltoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(unsigned long num)
|
||||||
|
{
|
||||||
|
char buf[1 + 3 * sizeof(unsigned long)];
|
||||||
|
ultoa(num, buf, 10);
|
||||||
|
return concat(buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(float num)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
char* string = dtostrf(num, 4, 2, buf);
|
||||||
|
return concat(string, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(double num)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
char* string = dtostrf(num, 4, 2, buf);
|
||||||
|
return concat(string, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::concat(const __FlashStringHelper * str)
|
||||||
|
{
|
||||||
|
if (!str) return 0;
|
||||||
|
int length = strlen_P((const char *) str);
|
||||||
|
if (length == 0) return 1;
|
||||||
|
unsigned int newlen = len + length;
|
||||||
|
if (!reserve(newlen)) return 0;
|
||||||
|
strcpy_P(buffer + len, (const char *) str);
|
||||||
|
len = newlen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Concatenate */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(c)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(num)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||||
|
{
|
||||||
|
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||||
|
if (!a.concat(rhs)) a.invalidate();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Comparison */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
int String::compareTo(const String &s) const
|
||||||
|
{
|
||||||
|
if (!buffer || !s.buffer) {
|
||||||
|
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
|
||||||
|
if (buffer && len > 0) return *(unsigned char *)buffer;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return strcmp(buffer, s.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equals(const String &s2) const
|
||||||
|
{
|
||||||
|
return (len == s2.len && compareTo(s2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equals(const char *cstr) const
|
||||||
|
{
|
||||||
|
if (len == 0) return (cstr == NULL || *cstr == 0);
|
||||||
|
if (cstr == NULL) return buffer[0] == 0;
|
||||||
|
return strcmp(buffer, cstr) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator<(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator>(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator<=(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::operator>=(const String &rhs) const
|
||||||
|
{
|
||||||
|
return compareTo(rhs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::equalsIgnoreCase( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if (this == &s2) return 1;
|
||||||
|
if (len != s2.len) return 0;
|
||||||
|
if (len == 0) return 1;
|
||||||
|
const char *p1 = buffer;
|
||||||
|
const char *p2 = s2.buffer;
|
||||||
|
while (*p1) {
|
||||||
|
if (tolower(*p1++) != tolower(*p2++)) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::startsWith( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if (len < s2.len) return 0;
|
||||||
|
return startsWith(s2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
|
||||||
|
{
|
||||||
|
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
|
||||||
|
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char String::endsWith( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if ( len < s2.len || !buffer || !s2.buffer) return 0;
|
||||||
|
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Character Access */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
char String::charAt(unsigned int loc) const
|
||||||
|
{
|
||||||
|
return operator[](loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::setCharAt(unsigned int loc, char c)
|
||||||
|
{
|
||||||
|
if (loc < len) buffer[loc] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
char & String::operator[](unsigned int index)
|
||||||
|
{
|
||||||
|
static char dummy_writable_char;
|
||||||
|
if (index >= len || !buffer) {
|
||||||
|
dummy_writable_char = 0;
|
||||||
|
return dummy_writable_char;
|
||||||
|
}
|
||||||
|
return buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
char String::operator[]( unsigned int index ) const
|
||||||
|
{
|
||||||
|
if (index >= len || !buffer) return 0;
|
||||||
|
return buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
|
||||||
|
{
|
||||||
|
if (!bufsize || !buf) return;
|
||||||
|
if (index >= len) {
|
||||||
|
buf[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned int n = bufsize - 1;
|
||||||
|
if (n > len - index) n = len - index;
|
||||||
|
strncpy((char *)buf, buffer + index, n);
|
||||||
|
buf[n] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Search */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
int String::indexOf(char c) const
|
||||||
|
{
|
||||||
|
return indexOf(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf( char ch, unsigned int fromIndex ) const
|
||||||
|
{
|
||||||
|
if (fromIndex >= len) return -1;
|
||||||
|
const char* temp = strchr(buffer + fromIndex, ch);
|
||||||
|
if (temp == NULL) return -1;
|
||||||
|
return temp - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf(const String &s2) const
|
||||||
|
{
|
||||||
|
return indexOf(s2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf(const String &s2, unsigned int fromIndex) const
|
||||||
|
{
|
||||||
|
if (fromIndex >= len) return -1;
|
||||||
|
const char *found = strstr(buffer + fromIndex, s2.buffer);
|
||||||
|
if (found == NULL) return -1;
|
||||||
|
return found - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf( char theChar ) const
|
||||||
|
{
|
||||||
|
return lastIndexOf(theChar, len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(char ch, unsigned int fromIndex) const
|
||||||
|
{
|
||||||
|
if (fromIndex >= len) return -1;
|
||||||
|
char tempchar = buffer[fromIndex + 1];
|
||||||
|
buffer[fromIndex + 1] = '\0';
|
||||||
|
char* temp = strrchr( buffer, ch );
|
||||||
|
buffer[fromIndex + 1] = tempchar;
|
||||||
|
if (temp == NULL) return -1;
|
||||||
|
return temp - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(const String &s2) const
|
||||||
|
{
|
||||||
|
return lastIndexOf(s2, len - s2.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
|
||||||
|
{
|
||||||
|
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
|
||||||
|
if (fromIndex >= len) fromIndex = len - 1;
|
||||||
|
int found = -1;
|
||||||
|
for (char *p = buffer; p <= buffer + fromIndex; p++) {
|
||||||
|
p = strstr(p, s2.buffer);
|
||||||
|
if (!p) break;
|
||||||
|
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::substring(unsigned int left, unsigned int right) const
|
||||||
|
{
|
||||||
|
if (left > right) {
|
||||||
|
unsigned int temp = right;
|
||||||
|
right = left;
|
||||||
|
left = temp;
|
||||||
|
}
|
||||||
|
String out;
|
||||||
|
if (left > len) return out;
|
||||||
|
if (right > len) right = len;
|
||||||
|
char temp = buffer[right]; // save the replaced character
|
||||||
|
buffer[right] = '\0';
|
||||||
|
out = buffer + left; // pointer arithmetic
|
||||||
|
buffer[right] = temp; //restore character
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Modification */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
void String::replace(char find, char replace)
|
||||||
|
{
|
||||||
|
if (!buffer) return;
|
||||||
|
for (char *p = buffer; *p; p++) {
|
||||||
|
if (*p == find) *p = replace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::replace(const String& find, const String& replace)
|
||||||
|
{
|
||||||
|
if (len == 0 || find.len == 0) return;
|
||||||
|
int diff = replace.len - find.len;
|
||||||
|
char *readFrom = buffer;
|
||||||
|
char *foundAt;
|
||||||
|
if (diff == 0) {
|
||||||
|
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||||
|
memcpy(foundAt, replace.buffer, replace.len);
|
||||||
|
readFrom = foundAt + replace.len;
|
||||||
|
}
|
||||||
|
} else if (diff < 0) {
|
||||||
|
char *writeTo = buffer;
|
||||||
|
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||||
|
unsigned int n = foundAt - readFrom;
|
||||||
|
memcpy(writeTo, readFrom, n);
|
||||||
|
writeTo += n;
|
||||||
|
memcpy(writeTo, replace.buffer, replace.len);
|
||||||
|
writeTo += replace.len;
|
||||||
|
readFrom = foundAt + find.len;
|
||||||
|
len += diff;
|
||||||
|
}
|
||||||
|
strcpy(writeTo, readFrom);
|
||||||
|
} else {
|
||||||
|
unsigned int size = len; // compute size needed for result
|
||||||
|
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||||
|
readFrom = foundAt + find.len;
|
||||||
|
size += diff;
|
||||||
|
}
|
||||||
|
if (size == len) return;
|
||||||
|
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
|
||||||
|
int index = len - 1;
|
||||||
|
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||||
|
readFrom = buffer + index + find.len;
|
||||||
|
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
|
||||||
|
len += diff;
|
||||||
|
buffer[len] = 0;
|
||||||
|
memcpy(buffer + index, replace.buffer, replace.len);
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::remove(unsigned int index){
|
||||||
|
if (index >= len) { return; }
|
||||||
|
int count = len - index;
|
||||||
|
remove(index, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::remove(unsigned int index, unsigned int count){
|
||||||
|
if (index >= len) { return; }
|
||||||
|
if (count <= 0) { return; }
|
||||||
|
if (index + count > len) { count = len - index; }
|
||||||
|
char *writeTo = buffer + index;
|
||||||
|
len = len - count;
|
||||||
|
strncpy(writeTo, buffer + index + count,len - index);
|
||||||
|
buffer[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::toLowerCase(void)
|
||||||
|
{
|
||||||
|
if (!buffer) return;
|
||||||
|
for (char *p = buffer; *p; p++) {
|
||||||
|
*p = tolower(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::toUpperCase(void)
|
||||||
|
{
|
||||||
|
if (!buffer) return;
|
||||||
|
for (char *p = buffer; *p; p++) {
|
||||||
|
*p = toupper(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::trim(void)
|
||||||
|
{
|
||||||
|
if (!buffer || len == 0) return;
|
||||||
|
char *begin = buffer;
|
||||||
|
while (isspace(*begin)) begin++;
|
||||||
|
char *end = buffer + len - 1;
|
||||||
|
while (isspace(*end) && end >= begin) end--;
|
||||||
|
len = end + 1 - begin;
|
||||||
|
if (begin > buffer) memcpy(buffer, begin, len);
|
||||||
|
buffer[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Parsing / Conversion */
|
||||||
|
/*********************************************/
|
||||||
|
|
||||||
|
long String::toInt(void) const
|
||||||
|
{
|
||||||
|
if (buffer) return atol(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float String::toFloat(void) const
|
||||||
|
{
|
||||||
|
if (buffer) return float(atof(buffer));
|
||||||
|
return 0;
|
||||||
|
}
|
224
hardware/digistump/avr/cores/pro/WString.h
Normal file
224
hardware/digistump/avr/cores/pro/WString.h
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
WString.h - String library for Wiring & Arduino
|
||||||
|
...mostly rewritten by Paul Stoffregen...
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||||
|
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef String_class_h
|
||||||
|
#define String_class_h
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
// When compiling programs with this class, the following gcc parameters
|
||||||
|
// dramatically increase performance and memory (RAM) efficiency, typically
|
||||||
|
// with little or no increase in code size.
|
||||||
|
// -felide-constructors
|
||||||
|
// -std=c++0x
|
||||||
|
|
||||||
|
class __FlashStringHelper;
|
||||||
|
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||||
|
|
||||||
|
// An inherited class for holding the result of a concatenation. These
|
||||||
|
// result objects are assumed to be writable by subsequent concatenations.
|
||||||
|
class StringSumHelper;
|
||||||
|
|
||||||
|
// The string class
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
// use a function pointer to allow for "if (s)" without the
|
||||||
|
// complications of an operator bool(). for more information, see:
|
||||||
|
// http://www.artima.com/cppsource/safebool.html
|
||||||
|
typedef void (String::*StringIfHelperType)() const;
|
||||||
|
void StringIfHelper() const {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
// creates a copy of the initial value.
|
||||||
|
// if the initial value is null or invalid, or if memory allocation
|
||||||
|
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||||
|
// be false).
|
||||||
|
String(const char *cstr = "");
|
||||||
|
String(const String &str);
|
||||||
|
String(const __FlashStringHelper *str);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String(String &&rval);
|
||||||
|
String(StringSumHelper &&rval);
|
||||||
|
#endif
|
||||||
|
explicit String(char c);
|
||||||
|
explicit String(unsigned char, unsigned char base=10);
|
||||||
|
explicit String(int, unsigned char base=10);
|
||||||
|
explicit String(unsigned int, unsigned char base=10);
|
||||||
|
explicit String(long, unsigned char base=10);
|
||||||
|
explicit String(unsigned long, unsigned char base=10);
|
||||||
|
explicit String(float, unsigned char decimalPlaces=2);
|
||||||
|
explicit String(double, unsigned char decimalPlaces=2);
|
||||||
|
~String(void);
|
||||||
|
|
||||||
|
// memory management
|
||||||
|
// return true on success, false on failure (in which case, the string
|
||||||
|
// is left unchanged). reserve(0), if successful, will validate an
|
||||||
|
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||||
|
unsigned char reserve(unsigned int size);
|
||||||
|
inline unsigned int length(void) const {return len;}
|
||||||
|
|
||||||
|
// creates a copy of the assigned value. if the value is null or
|
||||||
|
// invalid, or if the memory allocation fails, the string will be
|
||||||
|
// marked as invalid ("if (s)" will be false).
|
||||||
|
String & operator = (const String &rhs);
|
||||||
|
String & operator = (const char *cstr);
|
||||||
|
String & operator = (const __FlashStringHelper *str);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
String & operator = (String &&rval);
|
||||||
|
String & operator = (StringSumHelper &&rval);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// concatenate (works w/ built-in types)
|
||||||
|
|
||||||
|
// returns true on success, false on failure (in which case, the string
|
||||||
|
// is left unchanged). if the argument is null or invalid, the
|
||||||
|
// concatenation is considered unsucessful.
|
||||||
|
unsigned char concat(const String &str);
|
||||||
|
unsigned char concat(const char *cstr);
|
||||||
|
unsigned char concat(char c);
|
||||||
|
unsigned char concat(unsigned char c);
|
||||||
|
unsigned char concat(int num);
|
||||||
|
unsigned char concat(unsigned int num);
|
||||||
|
unsigned char concat(long num);
|
||||||
|
unsigned char concat(unsigned long num);
|
||||||
|
unsigned char concat(float num);
|
||||||
|
unsigned char concat(double num);
|
||||||
|
unsigned char concat(const __FlashStringHelper * str);
|
||||||
|
|
||||||
|
// if there's not enough memory for the concatenated value, the string
|
||||||
|
// will be left unchanged (but this isn't signalled in any way)
|
||||||
|
String & operator += (const String &rhs) {concat(rhs); return (*this);}
|
||||||
|
String & operator += (const char *cstr) {concat(cstr); return (*this);}
|
||||||
|
String & operator += (char c) {concat(c); return (*this);}
|
||||||
|
String & operator += (unsigned char num) {concat(num); return (*this);}
|
||||||
|
String & operator += (int num) {concat(num); return (*this);}
|
||||||
|
String & operator += (unsigned int num) {concat(num); return (*this);}
|
||||||
|
String & operator += (long num) {concat(num); return (*this);}
|
||||||
|
String & operator += (unsigned long num) {concat(num); return (*this);}
|
||||||
|
String & operator += (float num) {concat(num); return (*this);}
|
||||||
|
String & operator += (double num) {concat(num); return (*this);}
|
||||||
|
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
|
||||||
|
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
|
||||||
|
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||||
|
|
||||||
|
// comparison (only works w/ Strings and "strings")
|
||||||
|
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
|
||||||
|
int compareTo(const String &s) const;
|
||||||
|
unsigned char equals(const String &s) const;
|
||||||
|
unsigned char equals(const char *cstr) const;
|
||||||
|
unsigned char operator == (const String &rhs) const {return equals(rhs);}
|
||||||
|
unsigned char operator == (const char *cstr) const {return equals(cstr);}
|
||||||
|
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
|
||||||
|
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
|
||||||
|
unsigned char operator < (const String &rhs) const;
|
||||||
|
unsigned char operator > (const String &rhs) const;
|
||||||
|
unsigned char operator <= (const String &rhs) const;
|
||||||
|
unsigned char operator >= (const String &rhs) const;
|
||||||
|
unsigned char equalsIgnoreCase(const String &s) const;
|
||||||
|
unsigned char startsWith( const String &prefix) const;
|
||||||
|
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||||
|
unsigned char endsWith(const String &suffix) const;
|
||||||
|
|
||||||
|
// character acccess
|
||||||
|
char charAt(unsigned int index) const;
|
||||||
|
void setCharAt(unsigned int index, char c);
|
||||||
|
char operator [] (unsigned int index) const;
|
||||||
|
char& operator [] (unsigned int index);
|
||||||
|
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
|
||||||
|
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
|
||||||
|
{getBytes((unsigned char *)buf, bufsize, index);}
|
||||||
|
const char * c_str() const { return buffer; }
|
||||||
|
|
||||||
|
// search
|
||||||
|
int indexOf( char ch ) const;
|
||||||
|
int indexOf( char ch, unsigned int fromIndex ) const;
|
||||||
|
int indexOf( const String &str ) const;
|
||||||
|
int indexOf( const String &str, unsigned int fromIndex ) const;
|
||||||
|
int lastIndexOf( char ch ) const;
|
||||||
|
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
||||||
|
int lastIndexOf( const String &str ) const;
|
||||||
|
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
||||||
|
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
|
||||||
|
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
||||||
|
|
||||||
|
// modification
|
||||||
|
void replace(char find, char replace);
|
||||||
|
void replace(const String& find, const String& replace);
|
||||||
|
void remove(unsigned int index);
|
||||||
|
void remove(unsigned int index, unsigned int count);
|
||||||
|
void toLowerCase(void);
|
||||||
|
void toUpperCase(void);
|
||||||
|
void trim(void);
|
||||||
|
|
||||||
|
// parsing/conversion
|
||||||
|
long toInt(void) const;
|
||||||
|
float toFloat(void) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char *buffer; // the actual char array
|
||||||
|
unsigned int capacity; // the array length minus one (for the '\0')
|
||||||
|
unsigned int len; // the String length (not counting the '\0')
|
||||||
|
protected:
|
||||||
|
void init(void);
|
||||||
|
void invalidate(void);
|
||||||
|
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||||
|
unsigned char concat(const char *cstr, unsigned int length);
|
||||||
|
|
||||||
|
// copy and move
|
||||||
|
String & copy(const char *cstr, unsigned int length);
|
||||||
|
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||||
|
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
void move(String &rhs);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class StringSumHelper : public String
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StringSumHelper(const String &s) : String(s) {}
|
||||||
|
StringSumHelper(const char *p) : String(p) {}
|
||||||
|
StringSumHelper(char c) : String(c) {}
|
||||||
|
StringSumHelper(unsigned char num) : String(num) {}
|
||||||
|
StringSumHelper(int num) : String(num) {}
|
||||||
|
StringSumHelper(unsigned int num) : String(num) {}
|
||||||
|
StringSumHelper(long num) : String(num) {}
|
||||||
|
StringSumHelper(unsigned long num) : String(num) {}
|
||||||
|
StringSumHelper(float num) : String(num) {}
|
||||||
|
StringSumHelper(double num) : String(num) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
#endif // String_class_h
|
515
hardware/digistump/avr/cores/pro/binary.h
Normal file
515
hardware/digistump/avr/cores/pro/binary.h
Normal file
@ -0,0 +1,515 @@
|
|||||||
|
#ifndef Binary_h
|
||||||
|
#define Binary_h
|
||||||
|
|
||||||
|
#define B0 0
|
||||||
|
#define B00 0
|
||||||
|
#define B000 0
|
||||||
|
#define B0000 0
|
||||||
|
#define B00000 0
|
||||||
|
#define B000000 0
|
||||||
|
#define B0000000 0
|
||||||
|
#define B00000000 0
|
||||||
|
#define B1 1
|
||||||
|
#define B01 1
|
||||||
|
#define B001 1
|
||||||
|
#define B0001 1
|
||||||
|
#define B00001 1
|
||||||
|
#define B000001 1
|
||||||
|
#define B0000001 1
|
||||||
|
#define B00000001 1
|
||||||
|
#define B10 2
|
||||||
|
#define B010 2
|
||||||
|
#define B0010 2
|
||||||
|
#define B00010 2
|
||||||
|
#define B000010 2
|
||||||
|
#define B0000010 2
|
||||||
|
#define B00000010 2
|
||||||
|
#define B11 3
|
||||||
|
#define B011 3
|
||||||
|
#define B0011 3
|
||||||
|
#define B00011 3
|
||||||
|
#define B000011 3
|
||||||
|
#define B0000011 3
|
||||||
|
#define B00000011 3
|
||||||
|
#define B100 4
|
||||||
|
#define B0100 4
|
||||||
|
#define B00100 4
|
||||||
|
#define B000100 4
|
||||||
|
#define B0000100 4
|
||||||
|
#define B00000100 4
|
||||||
|
#define B101 5
|
||||||
|
#define B0101 5
|
||||||
|
#define B00101 5
|
||||||
|
#define B000101 5
|
||||||
|
#define B0000101 5
|
||||||
|
#define B00000101 5
|
||||||
|
#define B110 6
|
||||||
|
#define B0110 6
|
||||||
|
#define B00110 6
|
||||||
|
#define B000110 6
|
||||||
|
#define B0000110 6
|
||||||
|
#define B00000110 6
|
||||||
|
#define B111 7
|
||||||
|
#define B0111 7
|
||||||
|
#define B00111 7
|
||||||
|
#define B000111 7
|
||||||
|
#define B0000111 7
|
||||||
|
#define B00000111 7
|
||||||
|
#define B1000 8
|
||||||
|
#define B01000 8
|
||||||
|
#define B001000 8
|
||||||
|
#define B0001000 8
|
||||||
|
#define B00001000 8
|
||||||
|
#define B1001 9
|
||||||
|
#define B01001 9
|
||||||
|
#define B001001 9
|
||||||
|
#define B0001001 9
|
||||||
|
#define B00001001 9
|
||||||
|
#define B1010 10
|
||||||
|
#define B01010 10
|
||||||
|
#define B001010 10
|
||||||
|
#define B0001010 10
|
||||||
|
#define B00001010 10
|
||||||
|
#define B1011 11
|
||||||
|
#define B01011 11
|
||||||
|
#define B001011 11
|
||||||
|
#define B0001011 11
|
||||||
|
#define B00001011 11
|
||||||
|
#define B1100 12
|
||||||
|
#define B01100 12
|
||||||
|
#define B001100 12
|
||||||
|
#define B0001100 12
|
||||||
|
#define B00001100 12
|
||||||
|
#define B1101 13
|
||||||
|
#define B01101 13
|
||||||
|
#define B001101 13
|
||||||
|
#define B0001101 13
|
||||||
|
#define B00001101 13
|
||||||
|
#define B1110 14
|
||||||
|
#define B01110 14
|
||||||
|
#define B001110 14
|
||||||
|
#define B0001110 14
|
||||||
|
#define B00001110 14
|
||||||
|
#define B1111 15
|
||||||
|
#define B01111 15
|
||||||
|
#define B001111 15
|
||||||
|
#define B0001111 15
|
||||||
|
#define B00001111 15
|
||||||
|
#define B10000 16
|
||||||
|
#define B010000 16
|
||||||
|
#define B0010000 16
|
||||||
|
#define B00010000 16
|
||||||
|
#define B10001 17
|
||||||
|
#define B010001 17
|
||||||
|
#define B0010001 17
|
||||||
|
#define B00010001 17
|
||||||
|
#define B10010 18
|
||||||
|
#define B010010 18
|
||||||
|
#define B0010010 18
|
||||||
|
#define B00010010 18
|
||||||
|
#define B10011 19
|
||||||
|
#define B010011 19
|
||||||
|
#define B0010011 19
|
||||||
|
#define B00010011 19
|
||||||
|
#define B10100 20
|
||||||
|
#define B010100 20
|
||||||
|
#define B0010100 20
|
||||||
|
#define B00010100 20
|
||||||
|
#define B10101 21
|
||||||
|
#define B010101 21
|
||||||
|
#define B0010101 21
|
||||||
|
#define B00010101 21
|
||||||
|
#define B10110 22
|
||||||
|
#define B010110 22
|
||||||
|
#define B0010110 22
|
||||||
|
#define B00010110 22
|
||||||
|
#define B10111 23
|
||||||
|
#define B010111 23
|
||||||
|
#define B0010111 23
|
||||||
|
#define B00010111 23
|
||||||
|
#define B11000 24
|
||||||
|
#define B011000 24
|
||||||
|
#define B0011000 24
|
||||||
|
#define B00011000 24
|
||||||
|
#define B11001 25
|
||||||
|
#define B011001 25
|
||||||
|
#define B0011001 25
|
||||||
|
#define B00011001 25
|
||||||
|
#define B11010 26
|
||||||
|
#define B011010 26
|
||||||
|
#define B0011010 26
|
||||||
|
#define B00011010 26
|
||||||
|
#define B11011 27
|
||||||
|
#define B011011 27
|
||||||
|
#define B0011011 27
|
||||||
|
#define B00011011 27
|
||||||
|
#define B11100 28
|
||||||
|
#define B011100 28
|
||||||
|
#define B0011100 28
|
||||||
|
#define B00011100 28
|
||||||
|
#define B11101 29
|
||||||
|
#define B011101 29
|
||||||
|
#define B0011101 29
|
||||||
|
#define B00011101 29
|
||||||
|
#define B11110 30
|
||||||
|
#define B011110 30
|
||||||
|
#define B0011110 30
|
||||||
|
#define B00011110 30
|
||||||
|
#define B11111 31
|
||||||
|
#define B011111 31
|
||||||
|
#define B0011111 31
|
||||||
|
#define B00011111 31
|
||||||
|
#define B100000 32
|
||||||
|
#define B0100000 32
|
||||||
|
#define B00100000 32
|
||||||
|
#define B100001 33
|
||||||
|
#define B0100001 33
|
||||||
|
#define B00100001 33
|
||||||
|
#define B100010 34
|
||||||
|
#define B0100010 34
|
||||||
|
#define B00100010 34
|
||||||
|
#define B100011 35
|
||||||
|
#define B0100011 35
|
||||||
|
#define B00100011 35
|
||||||
|
#define B100100 36
|
||||||
|
#define B0100100 36
|
||||||
|
#define B00100100 36
|
||||||
|
#define B100101 37
|
||||||
|
#define B0100101 37
|
||||||
|
#define B00100101 37
|
||||||
|
#define B100110 38
|
||||||
|
#define B0100110 38
|
||||||
|
#define B00100110 38
|
||||||
|
#define B100111 39
|
||||||
|
#define B0100111 39
|
||||||
|
#define B00100111 39
|
||||||
|
#define B101000 40
|
||||||
|
#define B0101000 40
|
||||||
|
#define B00101000 40
|
||||||
|
#define B101001 41
|
||||||
|
#define B0101001 41
|
||||||
|
#define B00101001 41
|
||||||
|
#define B101010 42
|
||||||
|
#define B0101010 42
|
||||||
|
#define B00101010 42
|
||||||
|
#define B101011 43
|
||||||
|
#define B0101011 43
|
||||||
|
#define B00101011 43
|
||||||
|
#define B101100 44
|
||||||
|
#define B0101100 44
|
||||||
|
#define B00101100 44
|
||||||
|
#define B101101 45
|
||||||
|
#define B0101101 45
|
||||||
|
#define B00101101 45
|
||||||
|
#define B101110 46
|
||||||
|
#define B0101110 46
|
||||||
|
#define B00101110 46
|
||||||
|
#define B101111 47
|
||||||
|
#define B0101111 47
|
||||||
|
#define B00101111 47
|
||||||
|
#define B110000 48
|
||||||
|
#define B0110000 48
|
||||||
|
#define B00110000 48
|
||||||
|
#define B110001 49
|
||||||
|
#define B0110001 49
|
||||||
|
#define B00110001 49
|
||||||
|
#define B110010 50
|
||||||
|
#define B0110010 50
|
||||||
|
#define B00110010 50
|
||||||
|
#define B110011 51
|
||||||
|
#define B0110011 51
|
||||||
|
#define B00110011 51
|
||||||
|
#define B110100 52
|
||||||
|
#define B0110100 52
|
||||||
|
#define B00110100 52
|
||||||
|
#define B110101 53
|
||||||
|
#define B0110101 53
|
||||||
|
#define B00110101 53
|
||||||
|
#define B110110 54
|
||||||
|
#define B0110110 54
|
||||||
|
#define B00110110 54
|
||||||
|
#define B110111 55
|
||||||
|
#define B0110111 55
|
||||||
|
#define B00110111 55
|
||||||
|
#define B111000 56
|
||||||
|
#define B0111000 56
|
||||||
|
#define B00111000 56
|
||||||
|
#define B111001 57
|
||||||
|
#define B0111001 57
|
||||||
|
#define B00111001 57
|
||||||
|
#define B111010 58
|
||||||
|
#define B0111010 58
|
||||||
|
#define B00111010 58
|
||||||
|
#define B111011 59
|
||||||
|
#define B0111011 59
|
||||||
|
#define B00111011 59
|
||||||
|
#define B111100 60
|
||||||
|
#define B0111100 60
|
||||||
|
#define B00111100 60
|
||||||
|
#define B111101 61
|
||||||
|
#define B0111101 61
|
||||||
|
#define B00111101 61
|
||||||
|
#define B111110 62
|
||||||
|
#define B0111110 62
|
||||||
|
#define B00111110 62
|
||||||
|
#define B111111 63
|
||||||
|
#define B0111111 63
|
||||||
|
#define B00111111 63
|
||||||
|
#define B1000000 64
|
||||||
|
#define B01000000 64
|
||||||
|
#define B1000001 65
|
||||||
|
#define B01000001 65
|
||||||
|
#define B1000010 66
|
||||||
|
#define B01000010 66
|
||||||
|
#define B1000011 67
|
||||||
|
#define B01000011 67
|
||||||
|
#define B1000100 68
|
||||||
|
#define B01000100 68
|
||||||
|
#define B1000101 69
|
||||||
|
#define B01000101 69
|
||||||
|
#define B1000110 70
|
||||||
|
#define B01000110 70
|
||||||
|
#define B1000111 71
|
||||||
|
#define B01000111 71
|
||||||
|
#define B1001000 72
|
||||||
|
#define B01001000 72
|
||||||
|
#define B1001001 73
|
||||||
|
#define B01001001 73
|
||||||
|
#define B1001010 74
|
||||||
|
#define B01001010 74
|
||||||
|
#define B1001011 75
|
||||||
|
#define B01001011 75
|
||||||
|
#define B1001100 76
|
||||||
|
#define B01001100 76
|
||||||
|
#define B1001101 77
|
||||||
|
#define B01001101 77
|
||||||
|
#define B1001110 78
|
||||||
|
#define B01001110 78
|
||||||
|
#define B1001111 79
|
||||||
|
#define B01001111 79
|
||||||
|
#define B1010000 80
|
||||||
|
#define B01010000 80
|
||||||
|
#define B1010001 81
|
||||||
|
#define B01010001 81
|
||||||
|
#define B1010010 82
|
||||||
|
#define B01010010 82
|
||||||
|
#define B1010011 83
|
||||||
|
#define B01010011 83
|
||||||
|
#define B1010100 84
|
||||||
|
#define B01010100 84
|
||||||
|
#define B1010101 85
|
||||||
|
#define B01010101 85
|
||||||
|
#define B1010110 86
|
||||||
|
#define B01010110 86
|
||||||
|
#define B1010111 87
|
||||||
|
#define B01010111 87
|
||||||
|
#define B1011000 88
|
||||||
|
#define B01011000 88
|
||||||
|
#define B1011001 89
|
||||||
|
#define B01011001 89
|
||||||
|
#define B1011010 90
|
||||||
|
#define B01011010 90
|
||||||
|
#define B1011011 91
|
||||||
|
#define B01011011 91
|
||||||
|
#define B1011100 92
|
||||||
|
#define B01011100 92
|
||||||
|
#define B1011101 93
|
||||||
|
#define B01011101 93
|
||||||
|
#define B1011110 94
|
||||||
|
#define B01011110 94
|
||||||
|
#define B1011111 95
|
||||||
|
#define B01011111 95
|
||||||
|
#define B1100000 96
|
||||||
|
#define B01100000 96
|
||||||
|
#define B1100001 97
|
||||||
|
#define B01100001 97
|
||||||
|
#define B1100010 98
|
||||||
|
#define B01100010 98
|
||||||
|
#define B1100011 99
|
||||||
|
#define B01100011 99
|
||||||
|
#define B1100100 100
|
||||||
|
#define B01100100 100
|
||||||
|
#define B1100101 101
|
||||||
|
#define B01100101 101
|
||||||
|
#define B1100110 102
|
||||||
|
#define B01100110 102
|
||||||
|
#define B1100111 103
|
||||||
|
#define B01100111 103
|
||||||
|
#define B1101000 104
|
||||||
|
#define B01101000 104
|
||||||
|
#define B1101001 105
|
||||||
|
#define B01101001 105
|
||||||
|
#define B1101010 106
|
||||||
|
#define B01101010 106
|
||||||
|
#define B1101011 107
|
||||||
|
#define B01101011 107
|
||||||
|
#define B1101100 108
|
||||||
|
#define B01101100 108
|
||||||
|
#define B1101101 109
|
||||||
|
#define B01101101 109
|
||||||
|
#define B1101110 110
|
||||||
|
#define B01101110 110
|
||||||
|
#define B1101111 111
|
||||||
|
#define B01101111 111
|
||||||
|
#define B1110000 112
|
||||||
|
#define B01110000 112
|
||||||
|
#define B1110001 113
|
||||||
|
#define B01110001 113
|
||||||
|
#define B1110010 114
|
||||||
|
#define B01110010 114
|
||||||
|
#define B1110011 115
|
||||||
|
#define B01110011 115
|
||||||
|
#define B1110100 116
|
||||||
|
#define B01110100 116
|
||||||
|
#define B1110101 117
|
||||||
|
#define B01110101 117
|
||||||
|
#define B1110110 118
|
||||||
|
#define B01110110 118
|
||||||
|
#define B1110111 119
|
||||||
|
#define B01110111 119
|
||||||
|
#define B1111000 120
|
||||||
|
#define B01111000 120
|
||||||
|
#define B1111001 121
|
||||||
|
#define B01111001 121
|
||||||
|
#define B1111010 122
|
||||||
|
#define B01111010 122
|
||||||
|
#define B1111011 123
|
||||||
|
#define B01111011 123
|
||||||
|
#define B1111100 124
|
||||||
|
#define B01111100 124
|
||||||
|
#define B1111101 125
|
||||||
|
#define B01111101 125
|
||||||
|
#define B1111110 126
|
||||||
|
#define B01111110 126
|
||||||
|
#define B1111111 127
|
||||||
|
#define B01111111 127
|
||||||
|
#define B10000000 128
|
||||||
|
#define B10000001 129
|
||||||
|
#define B10000010 130
|
||||||
|
#define B10000011 131
|
||||||
|
#define B10000100 132
|
||||||
|
#define B10000101 133
|
||||||
|
#define B10000110 134
|
||||||
|
#define B10000111 135
|
||||||
|
#define B10001000 136
|
||||||
|
#define B10001001 137
|
||||||
|
#define B10001010 138
|
||||||
|
#define B10001011 139
|
||||||
|
#define B10001100 140
|
||||||
|
#define B10001101 141
|
||||||
|
#define B10001110 142
|
||||||
|
#define B10001111 143
|
||||||
|
#define B10010000 144
|
||||||
|
#define B10010001 145
|
||||||
|
#define B10010010 146
|
||||||
|
#define B10010011 147
|
||||||
|
#define B10010100 148
|
||||||
|
#define B10010101 149
|
||||||
|
#define B10010110 150
|
||||||
|
#define B10010111 151
|
||||||
|
#define B10011000 152
|
||||||
|
#define B10011001 153
|
||||||
|
#define B10011010 154
|
||||||
|
#define B10011011 155
|
||||||
|
#define B10011100 156
|
||||||
|
#define B10011101 157
|
||||||
|
#define B10011110 158
|
||||||
|
#define B10011111 159
|
||||||
|
#define B10100000 160
|
||||||
|
#define B10100001 161
|
||||||
|
#define B10100010 162
|
||||||
|
#define B10100011 163
|
||||||
|
#define B10100100 164
|
||||||
|
#define B10100101 165
|
||||||
|
#define B10100110 166
|
||||||
|
#define B10100111 167
|
||||||
|
#define B10101000 168
|
||||||
|
#define B10101001 169
|
||||||
|
#define B10101010 170
|
||||||
|
#define B10101011 171
|
||||||
|
#define B10101100 172
|
||||||
|
#define B10101101 173
|
||||||
|
#define B10101110 174
|
||||||
|
#define B10101111 175
|
||||||
|
#define B10110000 176
|
||||||
|
#define B10110001 177
|
||||||
|
#define B10110010 178
|
||||||
|
#define B10110011 179
|
||||||
|
#define B10110100 180
|
||||||
|
#define B10110101 181
|
||||||
|
#define B10110110 182
|
||||||
|
#define B10110111 183
|
||||||
|
#define B10111000 184
|
||||||
|
#define B10111001 185
|
||||||
|
#define B10111010 186
|
||||||
|
#define B10111011 187
|
||||||
|
#define B10111100 188
|
||||||
|
#define B10111101 189
|
||||||
|
#define B10111110 190
|
||||||
|
#define B10111111 191
|
||||||
|
#define B11000000 192
|
||||||
|
#define B11000001 193
|
||||||
|
#define B11000010 194
|
||||||
|
#define B11000011 195
|
||||||
|
#define B11000100 196
|
||||||
|
#define B11000101 197
|
||||||
|
#define B11000110 198
|
||||||
|
#define B11000111 199
|
||||||
|
#define B11001000 200
|
||||||
|
#define B11001001 201
|
||||||
|
#define B11001010 202
|
||||||
|
#define B11001011 203
|
||||||
|
#define B11001100 204
|
||||||
|
#define B11001101 205
|
||||||
|
#define B11001110 206
|
||||||
|
#define B11001111 207
|
||||||
|
#define B11010000 208
|
||||||
|
#define B11010001 209
|
||||||
|
#define B11010010 210
|
||||||
|
#define B11010011 211
|
||||||
|
#define B11010100 212
|
||||||
|
#define B11010101 213
|
||||||
|
#define B11010110 214
|
||||||
|
#define B11010111 215
|
||||||
|
#define B11011000 216
|
||||||
|
#define B11011001 217
|
||||||
|
#define B11011010 218
|
||||||
|
#define B11011011 219
|
||||||
|
#define B11011100 220
|
||||||
|
#define B11011101 221
|
||||||
|
#define B11011110 222
|
||||||
|
#define B11011111 223
|
||||||
|
#define B11100000 224
|
||||||
|
#define B11100001 225
|
||||||
|
#define B11100010 226
|
||||||
|
#define B11100011 227
|
||||||
|
#define B11100100 228
|
||||||
|
#define B11100101 229
|
||||||
|
#define B11100110 230
|
||||||
|
#define B11100111 231
|
||||||
|
#define B11101000 232
|
||||||
|
#define B11101001 233
|
||||||
|
#define B11101010 234
|
||||||
|
#define B11101011 235
|
||||||
|
#define B11101100 236
|
||||||
|
#define B11101101 237
|
||||||
|
#define B11101110 238
|
||||||
|
#define B11101111 239
|
||||||
|
#define B11110000 240
|
||||||
|
#define B11110001 241
|
||||||
|
#define B11110010 242
|
||||||
|
#define B11110011 243
|
||||||
|
#define B11110100 244
|
||||||
|
#define B11110101 245
|
||||||
|
#define B11110110 246
|
||||||
|
#define B11110111 247
|
||||||
|
#define B11111000 248
|
||||||
|
#define B11111001 249
|
||||||
|
#define B11111010 250
|
||||||
|
#define B11111011 251
|
||||||
|
#define B11111100 252
|
||||||
|
#define B11111101 253
|
||||||
|
#define B11111110 254
|
||||||
|
#define B11111111 255
|
||||||
|
|
||||||
|
#endif
|
15
hardware/digistump/avr/cores/pro/main.cpp
Normal file
15
hardware/digistump/avr/cores/pro/main.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
//OSCCAL = TUNED_OSCCAL_VALUE; //set the oscillator calibration value based on the pins_arduino.h file. If this is not set, it will be optimised away - it would boil down to 1 = 1;
|
||||||
|
init();
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
loop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
692
hardware/digistump/avr/cores/pro/wiring.c
Normal file
692
hardware/digistump/avr/cores/pro/wiring.c
Normal file
@ -0,0 +1,692 @@
|
|||||||
|
/*
|
||||||
|
wiring.c - Partial implementation of the Wiring API for the ATmega8.
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 970 2010-05-25 20:16:15Z dmellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-10-2009 for attiny45 Saposoft
|
||||||
|
Modified 20-11-2010 - B.Cook - Rewritten to use the various Veneers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
#if F_CPU >= 3000000L
|
||||||
|
|
||||||
|
#if !defined(__AVR_ATtiny167__) && !defined(__AVR_ATtiny87__)
|
||||||
|
#define timer0Prescaler 0b011
|
||||||
|
#else
|
||||||
|
#define timer0Prescaler 0b100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Timers with TCCR1 are slightly different.
|
||||||
|
#if defined(TCCR1) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
#define MillisTimer_Prescale_Index (0b0111)
|
||||||
|
#define ToneTimer_Prescale_Index (timer0Prescaler)
|
||||||
|
#elif defined(TCCR1) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
#define MillisTimer_Prescale_Index (timer0Prescaler)
|
||||||
|
#define ToneTimer_Prescale_Index (0b0111)
|
||||||
|
#elif defined(TCCR1E) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
#define MillisTimer_Prescale_Index (0b0111)
|
||||||
|
#define ToneTimer_Prescale_Index (timer0Prescaler)
|
||||||
|
#elif defined(TCCR1E) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
#define MillisTimer_Prescale_Index (timer0Prescaler)
|
||||||
|
#define ToneTimer_Prescale_Index (0b0111)
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
#define MillisTimer_Prescale_Index (0b011)
|
||||||
|
#define ToneTimer_Prescale_Index (timer0Prescaler)
|
||||||
|
#else
|
||||||
|
#define MillisTimer_Prescale_Index (timer0Prescaler)
|
||||||
|
#define ToneTimer_Prescale_Index (0b011)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MillisTimer_Prescale_Value (64)
|
||||||
|
#define ToneTimer_Prescale_Value (64)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(TCCR1) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
#define MillisTimer_Prescale_Index (0b0100)
|
||||||
|
#define ToneTimer_Prescale_Index (0b010)
|
||||||
|
#elif defined(TCCR1) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
#define MillisTimer_Prescale_Index (0b010)
|
||||||
|
#define ToneTimer_Prescale_Index (0b0100)
|
||||||
|
#elif defined(TCCR1E) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
#define MillisTimer_Prescale_Index (0b0100)
|
||||||
|
#define ToneTimer_Prescale_Index (0b010)
|
||||||
|
#elif defined(TCCR1E) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
#define MillisTimer_Prescale_Index (0b010)
|
||||||
|
#define ToneTimer_Prescale_Index (0b0100)
|
||||||
|
#else
|
||||||
|
#define MillisTimer_Prescale_Index (0b010)
|
||||||
|
#define ToneTimer_Prescale_Index (0b010)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MillisTimer_Prescale_Value (8)
|
||||||
|
#define ToneTimer_Prescale_Value (8)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// the prescaler is set so that the millis timer ticks every MillisTimer_Prescale_Value (64) clock cycles, and the
|
||||||
|
// the overflow handler is called every 256 ticks.
|
||||||
|
#define MICROSECONDS_PER_MILLIS_OVERFLOW (clockCyclesToMicroseconds(MillisTimer_Prescale_Value * 256))
|
||||||
|
|
||||||
|
// the whole number of milliseconds per millis timer overflow
|
||||||
|
#define MILLIS_INC (MICROSECONDS_PER_MILLIS_OVERFLOW / 1000)
|
||||||
|
|
||||||
|
// the fractional number of milliseconds per millis timer overflow. we shift right
|
||||||
|
// by three to fit these numbers into a byte. (for the clock speeds we care
|
||||||
|
// about - 8 and 16 MHz - this doesn't lose precision.)
|
||||||
|
#define FRACT_INC ((MICROSECONDS_PER_MILLIS_OVERFLOW % 1000) >> 3)
|
||||||
|
#define FRACT_MAX (1000 >> 3)
|
||||||
|
|
||||||
|
volatile unsigned long millis_timer_overflow_count = 0;
|
||||||
|
volatile unsigned long millis_timer_millis = 0;
|
||||||
|
static unsigned char millis_timer_fract = 0;
|
||||||
|
#if (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
|
||||||
|
#if defined(TIMER0_OVF_vect)
|
||||||
|
SIGNAL(TIMER0_OVF_vect)
|
||||||
|
#elif defined(TIM0_OVF_vect)
|
||||||
|
SIGNAL(TIM0_OVF_vect)
|
||||||
|
#else
|
||||||
|
#error cannot find Millis() timer overflow vector
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
|
||||||
|
#if defined(TIMER1_OVF_vect)
|
||||||
|
SIGNAL(TIMER1_OVF_vect)
|
||||||
|
#elif defined(TIM1_OVF_vect)
|
||||||
|
SIGNAL(TIM1_OVF_vect)
|
||||||
|
#else
|
||||||
|
#error cannot find Millis() timer overflow vector
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error Millis() timer not defined!
|
||||||
|
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// copy these to local variables so they can be stored in registers
|
||||||
|
// (volatile variables must be read from memory on every access)
|
||||||
|
unsigned long m = millis_timer_millis;
|
||||||
|
unsigned char f = millis_timer_fract;
|
||||||
|
|
||||||
|
/* rmv: The code below generates considerably less code (emtpy Sketch is 326 versus 304)...
|
||||||
|
|
||||||
|
m += MILLIS_INC;
|
||||||
|
f += FRACT_INC;
|
||||||
|
if (f >= FRACT_MAX) {
|
||||||
|
f -= FRACT_MAX;
|
||||||
|
m += 1;
|
||||||
|
}
|
||||||
|
...rmv */
|
||||||
|
|
||||||
|
f += FRACT_INC;
|
||||||
|
|
||||||
|
if (f >= FRACT_MAX)
|
||||||
|
{
|
||||||
|
f -= FRACT_MAX;
|
||||||
|
m += 1;
|
||||||
|
m += MILLIS_INC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m += MILLIS_INC;
|
||||||
|
}
|
||||||
|
|
||||||
|
millis_timer_fract = f;
|
||||||
|
millis_timer_millis = m;
|
||||||
|
millis_timer_overflow_count++;
|
||||||
|
|
||||||
|
|
||||||
|
//MICROSECONDS_PER_MILLIS_OVERFLOW=2048
|
||||||
|
//MILLIS_INC=2
|
||||||
|
//FRACT_INC=6
|
||||||
|
//FRACT_MAX=125
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long millis()
|
||||||
|
{
|
||||||
|
unsigned long m;
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
|
||||||
|
// disable interrupts while we read millis_timer_millis or we might get an
|
||||||
|
// inconsistent value (e.g. in the middle of a write to millis_timer_millis)
|
||||||
|
cli();
|
||||||
|
m = millis_timer_millis;
|
||||||
|
SREG = oldSREG;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long micros()
|
||||||
|
{
|
||||||
|
unsigned long m;
|
||||||
|
uint8_t oldSREG = SREG, t;
|
||||||
|
|
||||||
|
cli();
|
||||||
|
m = millis_timer_overflow_count;
|
||||||
|
#if defined(TCNT0) && (TIMER_TO_USE_FOR_MILLIS == 0) && !defined(TCW0)
|
||||||
|
t = TCNT0;
|
||||||
|
#elif defined(TCNT0L) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
t = TCNT0L;
|
||||||
|
#elif defined(TCNT1) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
t = TCNT1;
|
||||||
|
#elif defined(TCNT1L) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
t = TCNT1L;
|
||||||
|
#else
|
||||||
|
#error Millis()/Micros() timer not defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TIFR0) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
if ((TIFR0 & _BV(TOV0)) && (t < 255))
|
||||||
|
m++;
|
||||||
|
#elif defined(TIFR) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
if ((TIFR & _BV(TOV0)) && (t < 255))
|
||||||
|
m++;
|
||||||
|
#elif defined(TIFR1) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
if ((TIFR1 & _BV(TOV1)) && (t < 255))
|
||||||
|
m++;
|
||||||
|
#elif defined(TIFR) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
if ((TIFR & _BV(TOV1)) && (t < 255))
|
||||||
|
m++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SREG = oldSREG;
|
||||||
|
|
||||||
|
return ((m << 8) + t) * (MillisTimer_Prescale_Value / clockCyclesPerMicrosecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay(unsigned long ms)
|
||||||
|
{
|
||||||
|
uint16_t start = (uint16_t)micros();
|
||||||
|
while (ms > 0) {
|
||||||
|
if (((uint16_t)micros() - start) >= 1000) {
|
||||||
|
ms--;
|
||||||
|
start += 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
|
||||||
|
void delayMicroseconds(unsigned int us)
|
||||||
|
{
|
||||||
|
// call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable)
|
||||||
|
|
||||||
|
// calling avrlib's delay_us() function with low values (e.g. 1 or
|
||||||
|
// 2 microseconds) gives delays longer than desired.
|
||||||
|
//delay_us(us);
|
||||||
|
#if F_CPU >= 24000000L
|
||||||
|
// for the 24 MHz clock for the aventurous ones, trying to overclock
|
||||||
|
|
||||||
|
// zero delay fix
|
||||||
|
if (!us) return; // = 3 cycles, (4 when true)
|
||||||
|
|
||||||
|
// the following loop takes a 1/6 of a microsecond (4 cycles)
|
||||||
|
// per iteration, so execute it six times for each microsecond of
|
||||||
|
// delay requested.
|
||||||
|
us *= 6; // x6 us, = 7 cycles
|
||||||
|
|
||||||
|
// account for the time taken in the preceeding commands.
|
||||||
|
// we just burned 22 (24) cycles above, remove 5, (5*4=20)
|
||||||
|
// us is at least 6 so we can substract 5
|
||||||
|
us -= 5; //=2 cycles
|
||||||
|
|
||||||
|
#elif F_CPU >= 20000000L
|
||||||
|
// for the 20 MHz clock on rare Arduino boards
|
||||||
|
|
||||||
|
// for a one-microsecond delay, simply return. the overhead
|
||||||
|
// of the function call takes 18 (20) cycles, which is 1us
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"nop" "\n\t"
|
||||||
|
"nop" "\n\t"
|
||||||
|
"nop" "\n\t"
|
||||||
|
"nop"); //just waiting 4 cycles
|
||||||
|
if (us <= 1) return; // = 3 cycles, (4 when true)
|
||||||
|
|
||||||
|
// the following loop takes a 1/5 of a microsecond (4 cycles)
|
||||||
|
// per iteration, so execute it five times for each microsecond of
|
||||||
|
// delay requested.
|
||||||
|
us = (us << 2) + us; // x5 us, = 7 cycles
|
||||||
|
|
||||||
|
// account for the time taken in the preceeding commands.
|
||||||
|
// we just burned 26 (28) cycles above, remove 7, (7*4=28)
|
||||||
|
// us is at least 10 so we can substract 7
|
||||||
|
us -= 7; // 2 cycles
|
||||||
|
|
||||||
|
#elif F_CPU >= 16000000L
|
||||||
|
// for the 16 MHz clock on most Arduino boards
|
||||||
|
|
||||||
|
// for a one-microsecond delay, simply return. the overhead
|
||||||
|
// of the function call takes 14 (16) cycles, which is 1us
|
||||||
|
if (us <= 1) return; // = 3 cycles, (4 when true)
|
||||||
|
|
||||||
|
// the following loop takes 1/4 of a microsecond (4 cycles)
|
||||||
|
// per iteration, so execute it four times for each microsecond of
|
||||||
|
// delay requested.
|
||||||
|
us <<= 2; // x4 us, = 4 cycles
|
||||||
|
|
||||||
|
// account for the time taken in the preceeding commands.
|
||||||
|
// we just burned 19 (21) cycles above, remove 5, (5*4=20)
|
||||||
|
// us is at least 8 so we can substract 5
|
||||||
|
us -= 5; // = 2 cycles,
|
||||||
|
|
||||||
|
#elif F_CPU >= 12000000L
|
||||||
|
// for the 12 MHz clock if somebody is working with USB
|
||||||
|
|
||||||
|
// for a 1 microsecond delay, simply return. the overhead
|
||||||
|
// of the function call takes 14 (16) cycles, which is 1.5us
|
||||||
|
if (us <= 1) return; // = 3 cycles, (4 when true)
|
||||||
|
|
||||||
|
// the following loop takes 1/3 of a microsecond (4 cycles)
|
||||||
|
// per iteration, so execute it three times for each microsecond of
|
||||||
|
// delay requested.
|
||||||
|
us = (us << 1) + us; // x3 us, = 5 cycles
|
||||||
|
|
||||||
|
// account for the time taken in the preceeding commands.
|
||||||
|
// we just burned 20 (22) cycles above, remove 5, (5*4=20)
|
||||||
|
// us is at least 6 so we can substract 5
|
||||||
|
us -= 5; //2 cycles
|
||||||
|
|
||||||
|
#elif F_CPU >= 8000000L
|
||||||
|
// for the 8 MHz internal clock
|
||||||
|
|
||||||
|
// for a 1 and 2 microsecond delay, simply return. the overhead
|
||||||
|
// of the function call takes 14 (16) cycles, which is 2us
|
||||||
|
if (us <= 2) return; // = 3 cycles, (4 when true)
|
||||||
|
|
||||||
|
// the following loop takes 1/2 of a microsecond (4 cycles)
|
||||||
|
// per iteration, so execute it twice for each microsecond of
|
||||||
|
// delay requested.
|
||||||
|
us <<= 1; //x2 us, = 2 cycles
|
||||||
|
|
||||||
|
// account for the time taken in the preceeding commands.
|
||||||
|
// we just burned 17 (19) cycles above, remove 4, (4*4=16)
|
||||||
|
// us is at least 6 so we can substract 4
|
||||||
|
us -= 4; // = 2 cycles
|
||||||
|
|
||||||
|
#else
|
||||||
|
// for the 1 MHz internal clock (default settings for common AVR microcontrollers)
|
||||||
|
|
||||||
|
// the overhead of the function calls is 14 (16) cycles
|
||||||
|
if (us <= 16) return; //= 3 cycles, (4 when true)
|
||||||
|
if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22)
|
||||||
|
|
||||||
|
// compensate for the time taken by the preceeding and next commands (about 22 cycles)
|
||||||
|
us -= 22; // = 2 cycles
|
||||||
|
// the following loop takes 4 microseconds (4 cycles)
|
||||||
|
// per iteration, so execute it us/4 times
|
||||||
|
// us is at least 4, divided by 4 gives us 1 (no zero delay bug)
|
||||||
|
us >>= 2; // us div 4, = 4 cycles
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// busy wait
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"1: sbiw %0,1" "\n\t" // 2 cycles
|
||||||
|
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
|
||||||
|
);
|
||||||
|
// return = 4 cycles
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INITIALIZE_SECONDARY_TIMERS
|
||||||
|
static void initToneTimerInternal(void)
|
||||||
|
{
|
||||||
|
// Timer is processor clock divided by ToneTimer_Prescale_Index
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
TCCR0B &= ~((1<<CS02) | (1<<CS01) | (1<<CS00)); //stop the clock to configure
|
||||||
|
// Use the Tone Timer for phase correct PWM
|
||||||
|
sbi(TCCR0A, WGM00);
|
||||||
|
cbi(TCCR0A, WGM01);
|
||||||
|
cbi(TCCR0B, WGM02);
|
||||||
|
TCCR0B |= (ToneTimer_Prescale_Index << CS00);
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
|
||||||
|
TCCR1 &= ~((1<<CS13) | (1<<CS12) | (1<<CS11) | (1<<CS10)); //stop the clock to configure
|
||||||
|
// Use the Tone Timer for fast PWM as phase correct not supported by this timer
|
||||||
|
sbi(TCCR1, CTC1);
|
||||||
|
#if !defined(__AVR_ATtiny85__)
|
||||||
|
sbi(TCCR1, PWM1A); //for the tiny 85, Timer0 is used instead.
|
||||||
|
#endif
|
||||||
|
sbi(GTCCR, PWM1B);
|
||||||
|
OCR1C = 0xFF; //Use 255 as the top to match with the others as this module doesn't have a 8bit PWM mode.
|
||||||
|
TCCR1 |= (ToneTimer_Prescale_Index << CS10);
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
|
||||||
|
TCCR1B &= ~((1<<CS13) | (1<<CS12) | (1<<CS11) | (1<<CS10)); //stop the clock to configure
|
||||||
|
// Use the Tone Timer for phase correct PWM
|
||||||
|
sbi(TCCR1A, PWM1A);
|
||||||
|
sbi(TCCR1A, PWM1B);
|
||||||
|
sbi(TCCR1C, PWM1D);
|
||||||
|
cbi(TCCR1D, WGM11);
|
||||||
|
sbi(TCCR1D, WGM10);
|
||||||
|
TCCR1B |= (ToneTimer_Prescale_Index << CS10);
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
TCCR1B &= ~((1<<CS12) | (1<<CS11) | (1<<CS10)); //stop the clock to configure
|
||||||
|
// Use the Tone Timer for phase correct PWM
|
||||||
|
sbi(TCCR1A, WGM10);
|
||||||
|
cbi(TCCR1A, WGM11);
|
||||||
|
cbi(TCCR1B, WGM12);
|
||||||
|
cbi(TCCR1B, WGM13);
|
||||||
|
TCCR1B |= (ToneTimer_Prescale_Index << CS10); //set the clock
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void initToneTimer(void)
|
||||||
|
{
|
||||||
|
// Ensure the timer is in the same state as power-up
|
||||||
|
#if (TIMER_TO_USE_FOR_TONE == 0)
|
||||||
|
TCCR0B = (0<<FOC0A) | (0<<FOC0B) | (0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
|
||||||
|
TCCR0A = (0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT0 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR0A = 0;
|
||||||
|
OCR0B = 0;
|
||||||
|
#if defined(TIMSK)
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#elif defined(TIMSK1)
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR0 |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1)
|
||||||
|
// Turn off Clear on Compare Match, turn off PWM A, disconnect the timer from the output pin, stop the clock
|
||||||
|
TCCR1 = (0<<CTC1) | (0<<PWM1A) | (0<<COM1A1) | (0<<COM1A0) | (0<<CS13) | (0<<CS12) | (0<<CS11) | (0<<CS10);
|
||||||
|
// Turn off PWM A, disconnect the timer from the output pin, no Force Output Compare Match, no Prescaler Reset
|
||||||
|
GTCCR &= ~((1<<PWM1B) | (1<<COM1B1) | (1<<COM1B0) | (1<<FOC1B) | (1<<FOC1A) | (1<<PSR1));
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
OCR1C = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK &= ~((1<<OCIE1A) | (1<<OCIE1B) | (1<<TOIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<OCF1A) | (1<<OCF1B) | (1<<TOV1));
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1) && defined(TCCR1E)
|
||||||
|
TCCR1A = 0;
|
||||||
|
TCCR1B = 0;
|
||||||
|
TCCR1C = 0;
|
||||||
|
TCCR1D = 0;
|
||||||
|
TCCR1E = 0;
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
OCR1C = 0;
|
||||||
|
OCR1D = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<OCIE1D));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<OCF1D));
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_TONE == 1)
|
||||||
|
// Turn off Input Capture Noise Canceler, Input Capture Edge Select on Falling, stop the clock
|
||||||
|
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
|
||||||
|
// Disconnect the timer from the output pins, Set Waveform Generation Mode to Normal
|
||||||
|
TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
#if defined(TIMSK)
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
|
||||||
|
#elif defined(TIMSK1)
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK1 &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR1 |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if INITIALIZE_SECONDARY_TIMERS
|
||||||
|
// Prepare the timer for PWM
|
||||||
|
initToneTimerInternal();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if F_CPU == 20000000
|
||||||
|
// 20 MHz / 128 ~= 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER B111
|
||||||
|
#elif F_CPU == 18432000
|
||||||
|
// 18.432 MHz / 128 ~= 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER B111
|
||||||
|
#elif F_CPU == 16000000
|
||||||
|
// 16 MHz / 128 = 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER B111
|
||||||
|
#elif F_CPU == 12000000
|
||||||
|
// 12 MHz / 64 ~= 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER B110
|
||||||
|
#elif F_CPU == 8000000
|
||||||
|
// 8 MHz / 64 = 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER B110
|
||||||
|
#elif F_CPU == 1000000
|
||||||
|
// 1 MHz / 8 = 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER B011
|
||||||
|
#elif F_CPU == 128000
|
||||||
|
// 128 kHz / 2 = 64 KHz -> This is the closest you can get, the prescaler is 2
|
||||||
|
#define ADC_ARDUINO_PRESCALER B000
|
||||||
|
#else
|
||||||
|
#error Add an entry for the selected processor speed.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
// In case the bootloader left our millis timer in a bad way
|
||||||
|
#if defined( HAVE_BOOTLOADER ) && HAVE_BOOTLOADER
|
||||||
|
// Ensure the timer is in the same state as power-up
|
||||||
|
#if (TIMER_TO_USE_FOR_MILLIS == 0) && defined(WGM01)
|
||||||
|
TCCR0B = 0;
|
||||||
|
TCCR0A = 0;
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT0 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR0A = 0;
|
||||||
|
#ifdef OCR0B
|
||||||
|
OCR0B = 0;
|
||||||
|
#endif
|
||||||
|
#if defined(TIMSK)
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#elif defined(TIMSK1)
|
||||||
|
#ifdef OCIE0B
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR0 |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#else
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK0 &= ~((1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR0 |= ((1<<OCF0A) | (1<<TOV0));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 0) && defined(TCW0)
|
||||||
|
TCCR0A = 0;
|
||||||
|
TCCR0B = 0;
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT0 = 0;
|
||||||
|
#if defined(TIMSK)
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#if defined(TICIE0)
|
||||||
|
cbi(TIMSK,TICIE0);
|
||||||
|
sbi(TIFR0,ICF0);
|
||||||
|
#endif
|
||||||
|
#elif defined(TIMSK1)
|
||||||
|
// Disable all Timer0 interrupts
|
||||||
|
TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0));
|
||||||
|
// Clear the Timer0 interrupt flags
|
||||||
|
TIFR0 |= ((1<<OCF0B) | (1<<OCF0A) | (1<<TOV0));
|
||||||
|
#if defined(TICIE0)
|
||||||
|
cbi(TIMSK0,TICIE0);
|
||||||
|
sbi(TIFR0,ICF0);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1) && defined(TCCR1)
|
||||||
|
// Turn off Clear on Compare Match, turn off PWM A, disconnect the timer from the output pin, stop the clock
|
||||||
|
TCCR1 = (0<<CTC1) | (0<<PWM1A) | (0<<COM1A1) | (0<<COM1A0) | (0<<CS13) | (0<<CS12) | (0<<CS11) | (0<<CS10);
|
||||||
|
// Turn off PWM A, disconnect the timer from the output pin, no Force Output Compare Match, no Prescaler Reset
|
||||||
|
GTCCR &= ~((1<<PWM1B) | (1<<COM1B1) | (1<<COM1B0) | (1<<FOC1B) | (1<<FOC1A) | (1<<PSR1));
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
OCR1C = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK = 0;
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<OCF1A) | (1<<OCF1B) | (1<<TOV1));
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1) && defined(TCCR1E)
|
||||||
|
TCCR1A = 0;
|
||||||
|
TCCR1B = 0;
|
||||||
|
TCCR1C = 0;
|
||||||
|
TCCR1D = 0;
|
||||||
|
TCCR1E = 0;
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<OCIE1D));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<OCF1D));
|
||||||
|
|
||||||
|
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
// Turn off Input Capture Noise Canceler, Input Capture Edge Select on Falling, stop the clock
|
||||||
|
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
|
||||||
|
// Disconnect the timer from the output pins, Set Waveform Generation Mode to Normal
|
||||||
|
TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
|
||||||
|
// Reset the count to zero
|
||||||
|
TCNT1 = 0;
|
||||||
|
// Set the output compare registers to zero
|
||||||
|
OCR1A = 0;
|
||||||
|
OCR1B = 0;
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
#if defined(TIMSK)
|
||||||
|
TIMSK &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
|
||||||
|
#elif defined(TIMSK1)
|
||||||
|
// Disable all Timer1 interrupts
|
||||||
|
TIMSK1 &= ~((1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B) | (1<<ICIE1));
|
||||||
|
// Clear the Timer1 interrupt flags
|
||||||
|
TIFR1 |= ((1<<TOV1) | (1<<OCF1A) | (1<<OCF1B) | (1<<ICF1));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use the Millis Timer for fast PWM (unless it doesn't have an output).
|
||||||
|
#if (TIMER_TO_USE_FOR_MILLIS == 0) && defined(WGM01)
|
||||||
|
sbi(TCCR0A, WGM01);
|
||||||
|
sbi(TCCR0A, WGM00);
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1) && defined(TCCR1)
|
||||||
|
sbi(TCCR1, CTC1);
|
||||||
|
//#if !defined(__AVR_ATtiny85__)
|
||||||
|
// sbi(TCCR1, PWM1A); //for the tiny 85, Timer0 is used instead.
|
||||||
|
//#endif
|
||||||
|
//sbi(GTCCR, PWM1B);
|
||||||
|
OCR1C = 0xFF; //Use 255 as the top to match with the others as this module doesn't have a 8bit PWM mode.
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1) && defined(TCCR1E)
|
||||||
|
sbi(TCCR1C, PWM1D);
|
||||||
|
sbi(TCCR1A, PWM1A);
|
||||||
|
sbi(TCCR1A, PWM1B);
|
||||||
|
cbi(TCCR1E, WGM10); //fast pwm mode
|
||||||
|
cbi(TCCR1E, WGM11);
|
||||||
|
OCR1C = 0xFF; //Use 255 as the top to match with the others as this module doesn't have a 8bit PWM mode.
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
sbi(TCCR1A, WGM10);
|
||||||
|
sbi(TCCR1B, WGM12);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Millis timer is always processor clock divided by MillisTimer_Prescale_Value (64)
|
||||||
|
#if (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
TCCR0B = (TCCR0B & ~((1<<CS02)|(1<<CS01)|(1<<CS00))) | (MillisTimer_Prescale_Index << CS00);
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1) && defined(TCCR1)
|
||||||
|
TCCR1 = (TCCR1 & ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10))) | (MillisTimer_Prescale_Index << CS10);
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1) && defined(TCCR1E)
|
||||||
|
TCCR1B = (TCCR1B & ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10))) | (MillisTimer_Prescale_Index << CS10);
|
||||||
|
#elif (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
TCCR1B = (TCCR1B & ~((1<<CS12)|(1<<CS11)|(1<<CS10))) | (MillisTimer_Prescale_Index << CS10);
|
||||||
|
#endif
|
||||||
|
// this needs to be called before setup() or some functions won't work there
|
||||||
|
sei();
|
||||||
|
|
||||||
|
// Enable the overlow interrupt (this is the basic system tic-toc for millis)
|
||||||
|
#if defined(TIMSK) && defined(TOIE0) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
sbi(TIMSK, TOIE0);
|
||||||
|
#elif defined(TIMSK0) && defined(TOIE0) && (TIMER_TO_USE_FOR_MILLIS == 0)
|
||||||
|
sbi(TIMSK0, TOIE0);
|
||||||
|
#elif defined(TIMSK) && defined(TOIE1) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
sbi(TIMSK, TOIE1);
|
||||||
|
#elif defined(TIMSK1) && defined(TOIE1) && (TIMER_TO_USE_FOR_MILLIS == 1)
|
||||||
|
sbi(TIMSK1, TOIE1);
|
||||||
|
#else
|
||||||
|
#error Millis() Timer overflow interrupt not set correctly
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize the timer used for Tone
|
||||||
|
#if INITIALIZE_SECONDARY_TIMERS
|
||||||
|
initToneTimerInternal();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize the ADC
|
||||||
|
#if defined( INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER ) && INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
|
||||||
|
#if defined(ADCSRA)
|
||||||
|
// set a2d prescale factor
|
||||||
|
ADCSRA = (ADCSRA & ~((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0))) | (ADC_ARDUINO_PRESCALER << ADPS0) | (1<<ADEN);
|
||||||
|
// enable a2d conversions
|
||||||
|
sbi(ADCSRA, ADEN);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
175
hardware/digistump/avr/cores/pro/wiring_analog.c
Normal file
175
hardware/digistump/avr/cores/pro/wiring_analog.c
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
wiring_analog.c - analog input and output
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-10-2009 for attiny45 Saposoft
|
||||||
|
Corrected 17-05-2010 for ATtiny84 B.Cook
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
#ifndef DEFAULT
|
||||||
|
//For those with no ADC, need to define default.
|
||||||
|
#define DEFAULT (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t analog_reference = DEFAULT;
|
||||||
|
|
||||||
|
void analogReference(uint8_t mode)
|
||||||
|
{
|
||||||
|
// can't actually set the register here because the default setting
|
||||||
|
// will connect AVCC and the AREF pin, which would cause a short if
|
||||||
|
// there's something connected to AREF.
|
||||||
|
// fix? Validate the mode?
|
||||||
|
analog_reference = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int analogRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
#if defined( NUM_DIGITAL_PINS )
|
||||||
|
if ( pin >= NUM_DIGITAL_PINS ) pin -= NUM_DIGITAL_PINS; // allow for channel or pin numbers
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// fix? Validate pin?
|
||||||
|
if(pin >= NUM_ANALOG_INPUTS) return 0; //Not a valid pin.
|
||||||
|
//if(pin < 4) return 9; //Not a valid pin.
|
||||||
|
#ifndef ADCSRA
|
||||||
|
return digitalRead(analogInputToDigitalPin(pin)) ? 1023 : 0; //No ADC, so read as a digital pin instead.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ADMUX)
|
||||||
|
#if defined(MUX4)
|
||||||
|
ADMUX = ((analog_reference & 0x03) << REFS0) | ((pin & 0x1F) << MUX0); //select the channel and reference
|
||||||
|
#elif defined(MUX3)
|
||||||
|
ADMUX = ((analog_reference & 0x03) << REFS0) | ((pin & 0x0F) << MUX0); //select the channel and reference
|
||||||
|
#else
|
||||||
|
ADMUX = ((analog_reference & 0x03) << REFS0) | ((pin & 0x07) << MUX0); //select the channel and reference
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(REFS2)
|
||||||
|
ADMUX |= (((analog_reference & 0x04) >> 2) << REFS2); //some have an extra reference bit in a weird position.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_ADC) && HAVE_ADC
|
||||||
|
sbi(ADCSRA, ADSC); //Start conversion
|
||||||
|
|
||||||
|
while(ADCSRA & (1<<ADSC)); //Wait for conversion to complete.
|
||||||
|
|
||||||
|
uint8_t low = ADCL;
|
||||||
|
uint8_t high = ADCH;
|
||||||
|
return (high << 8) | low;
|
||||||
|
#else
|
||||||
|
return LOW;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// Right now, PWM output only works on the pins with
|
||||||
|
// hardware support. These are defined in the appropriate
|
||||||
|
// pins_*.c file. For the rest of the pins, we default
|
||||||
|
// to digital output.
|
||||||
|
void analogWrite(uint8_t pin, int val)
|
||||||
|
{
|
||||||
|
// We need to make sure the PWM output is enabled for those pins
|
||||||
|
// that support it, as we turn it off when digitally reading or
|
||||||
|
// writing with them. Also, make sure the pin is in output mode
|
||||||
|
// for consistenty with Wiring, which doesn't require a pinMode
|
||||||
|
// call for the analog output pins.
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
|
||||||
|
if (val <= 0)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
else if (val >= 255)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t timer = digitalPinToTimer(pin);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
if( timer == TIMER0B){
|
||||||
|
// connect pwm to pin on timer 0, channel B
|
||||||
|
sbi(TCCR0A, COM0B1);
|
||||||
|
cbi(TCCR0A, COM0B0);
|
||||||
|
OCR0B = val; // set pwm duty
|
||||||
|
} else
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
if( timer == TIMER1A){
|
||||||
|
// connect pwm to pin on timer 1, channel A
|
||||||
|
sbi(TCCR1A, COM1A1);
|
||||||
|
sbi(TCCR1A, WGM10);
|
||||||
|
cbi(TCCR1A, COM1A0);
|
||||||
|
sbi(TCCR1B, WGM10);
|
||||||
|
sbi(TCCR1B, CS11);
|
||||||
|
//sbi(TCCR1B, CS10);
|
||||||
|
|
||||||
|
cbi(TCCR1D, OC1AV);
|
||||||
|
sbi(TCCR1D, OC1AU);
|
||||||
|
cbi(TCCR1D, OC1AW);
|
||||||
|
cbi(TCCR1D, OC1AX);
|
||||||
|
|
||||||
|
OCR1A = val; // set pwm duty
|
||||||
|
} else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if( timer == TIMER1B){
|
||||||
|
// connect pwm to pin on timer 1, channel B
|
||||||
|
sbi(TCCR1A, COM1B1);
|
||||||
|
sbi(TCCR1A, WGM10);
|
||||||
|
cbi(TCCR1A, COM1B0);
|
||||||
|
sbi(TCCR1B, WGM10);
|
||||||
|
sbi(TCCR1B, CS11);
|
||||||
|
//sbi(TCCR1B, CS10);
|
||||||
|
|
||||||
|
cbi(TCCR1D, OC1BV);
|
||||||
|
sbi(TCCR1D, OC1BU);
|
||||||
|
cbi(TCCR1D, OC1BW);
|
||||||
|
cbi(TCCR1D, OC1BX);
|
||||||
|
|
||||||
|
OCR1B = val; // set pwm duty
|
||||||
|
} else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
if (val < 128)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
160
hardware/digistump/avr/cores/pro/wiring_digital.c
Normal file
160
hardware/digistump/avr/cores/pro/wiring_digital.c
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
wiring_digital.c - digital input and output functions
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-10-2009 for attiny45 Saposoft
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ARDUINO_MAIN
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
void pinMode(uint8_t pin, uint8_t mode)
|
||||||
|
{
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
volatile uint8_t *reg, *out;
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN) return;
|
||||||
|
|
||||||
|
reg = portModeRegister(port);
|
||||||
|
out = portOutputRegister(port);
|
||||||
|
|
||||||
|
if (mode == INPUT) {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*reg &= ~bit;
|
||||||
|
*out &= ~bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
} else if (mode == INPUT_PULLUP) {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*reg &= ~bit;
|
||||||
|
*out |= bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
} else {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*reg |= bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void turnOffPWM(uint8_t timer)
|
||||||
|
{
|
||||||
|
#if defined(TCCR0A) && defined(COM0A1)
|
||||||
|
if( timer == TIMER0A){
|
||||||
|
cbi(TCCR0A, COM0A1);
|
||||||
|
cbi(TCCR0A, COM0A0);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR0A) && defined(COM0B1)
|
||||||
|
if( timer == TIMER0B){
|
||||||
|
cbi(TCCR0A, COM0B1);
|
||||||
|
cbi(TCCR0A, COM0B0);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR1A) && defined(COM1A1)
|
||||||
|
if( timer == TIMER1A){
|
||||||
|
cbi(TCCR1A, COM1A1);
|
||||||
|
cbi(TCCR1A, COM1A0);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR1) && defined(COM1A1)
|
||||||
|
if(timer == TIMER1A){
|
||||||
|
cbi(TCCR1, COM1A1);
|
||||||
|
cbi(TCCR1, COM1A0);
|
||||||
|
#ifdef OC1AX
|
||||||
|
cbi(TCCR1D, OC1AX);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR1A) && defined(COM1B1)
|
||||||
|
if( timer == TIMER1B){
|
||||||
|
cbi(TCCR1A, COM1B1);
|
||||||
|
cbi(TCCR1A, COM1B0);
|
||||||
|
#ifdef OC1BV
|
||||||
|
cbi(TCCR1D, OC1BV);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TCCR1) && defined(COM1B1)
|
||||||
|
if( timer == TIMER1B){
|
||||||
|
cbi(GTCCR, COM1B1);
|
||||||
|
cbi(GTCCR, COM1B0);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void digitalWrite(uint8_t pin, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t timer = digitalPinToTimer(pin);
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
volatile uint8_t *out;
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN) return;
|
||||||
|
|
||||||
|
// If the pin that support PWM output, we need to turn it off
|
||||||
|
// before doing a digital write.
|
||||||
|
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
|
||||||
|
|
||||||
|
out = portOutputRegister(port);
|
||||||
|
|
||||||
|
if (val == LOW) {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*out &= ~bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
} else {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*out |= bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int digitalRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
uint8_t timer = digitalPinToTimer(pin);
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN) return LOW;
|
||||||
|
|
||||||
|
// If the pin that support PWM output, we need to turn it off
|
||||||
|
// before getting a digital reading.
|
||||||
|
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
|
||||||
|
|
||||||
|
if (*portInputRegister(port) & bit) return HIGH;
|
||||||
|
return LOW;
|
||||||
|
}
|
178
hardware/digistump/avr/cores/pro/wiring_private.h
Normal file
178
hardware/digistump/avr/cores/pro/wiring_private.h
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
wiring_private.h - Internal header file.
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WiringPrivate_h
|
||||||
|
#define WiringPrivate_h
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef cbi
|
||||||
|
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||||
|
#endif
|
||||||
|
#ifndef sbi
|
||||||
|
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT0_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_0_vect EXT_INT0_vect
|
||||||
|
#elif defined( INT0_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_0_vect INT0_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT1_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_1_vect EXT_INT1_vect
|
||||||
|
#elif defined( INT1_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_1_vect INT1_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT2_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_2_vect EXT_INT2_vect
|
||||||
|
#elif defined( INT2_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_2_vect INT2_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT3_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_3_vect EXT_INT3_vect
|
||||||
|
#elif defined( INT3_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_3_vect INT3_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT4_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_4_vect EXT_INT4_vect
|
||||||
|
#elif defined( INT4_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_4_vect INT4_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT5_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_5_vect EXT_INT5_vect
|
||||||
|
#elif defined( INT5_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_5_vect INT5_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT6_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_6_vect EXT_INT6_vect
|
||||||
|
#elif defined( INT6_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_6_vect INT6_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT7_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_7_vect EXT_INT7_vect
|
||||||
|
#elif defined( INT7_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_7_vect INT7_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT8_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_8_vect EXT_INT8_vect
|
||||||
|
#elif defined( INT8_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_8_vect INT8_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT9_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_9_vect EXT_INT9_vect
|
||||||
|
#elif defined( INT9_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_9_vect INT9_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXTERNAL_INTERRUPT_9_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (10)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_8_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (9)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_7_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (8)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_6_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (7)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_5_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (6)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_4_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (5)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_3_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (4)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_2_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (3)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_1_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (2)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_0_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (1)
|
||||||
|
#else
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
#define EXTERNAL_INTERRUPT_0 (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2
|
||||||
|
#define EXTERNAL_INTERRUPT_1 (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 3
|
||||||
|
#define EXTERNAL_INTERRUPT_2 (2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 4
|
||||||
|
#define EXTERNAL_INTERRUPT_3 (3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 5
|
||||||
|
#define EXTERNAL_INTERRUPT_4 (4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 6
|
||||||
|
#define EXTERNAL_INTERRUPT_5 (5)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 7
|
||||||
|
#define EXTERNAL_INTERRUPT_6 (6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 8
|
||||||
|
#define EXTERNAL_INTERRUPT_7 (7)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 9
|
||||||
|
#define EXTERNAL_INTERRUPT_8 (8)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 10
|
||||||
|
#define EXTERNAL_INTERRUPT_9 (9)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*voidFuncPtr)(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
69
hardware/digistump/avr/cores/pro/wiring_pulse.c
Normal file
69
hardware/digistump/avr/cores/pro/wiring_pulse.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
wiring_pulse.c - pulseIn() function
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
|
||||||
|
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
|
||||||
|
* to 3 minutes in length, but must be called at least a few dozen microseconds
|
||||||
|
* before the start of the pulse. */
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
|
||||||
|
{
|
||||||
|
// cache the port and bit of the pin in order to speed up the
|
||||||
|
// pulse width measuring loop and achieve finer resolution. calling
|
||||||
|
// digitalRead() instead yields much coarser resolution.
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
uint8_t stateMask = (state ? bit : 0);
|
||||||
|
unsigned long width = 0; // keep initialization out of time critical area
|
||||||
|
|
||||||
|
// convert the timeout from microseconds to a number of times through
|
||||||
|
// the initial loop; it takes 16 clock cycles per iteration.
|
||||||
|
unsigned long numloops = 0;
|
||||||
|
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
|
||||||
|
|
||||||
|
// wait for any previous pulse to end
|
||||||
|
while ((*portInputRegister(port) & bit) == stateMask)
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// wait for the pulse to start
|
||||||
|
while ((*portInputRegister(port) & bit) != stateMask)
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// wait for the pulse to stop
|
||||||
|
while ((*portInputRegister(port) & bit) == stateMask) {
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
width++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the reading to microseconds. The loop has been determined
|
||||||
|
// to be 20 clock cycles long and have about 16 clocks between the edge
|
||||||
|
// and the start of the loop. There will be some error introduced by
|
||||||
|
// the interrupt handlers.
|
||||||
|
return clockCyclesToMicroseconds(width * 21 + 16);
|
||||||
|
}
|
55
hardware/digistump/avr/cores/pro/wiring_shift.c
Normal file
55
hardware/digistump/avr/cores/pro/wiring_shift.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
wiring_shift.c - shiftOut() function
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
|
||||||
|
uint8_t value = 0;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
digitalWrite(clockPin, HIGH);
|
||||||
|
if (bitOrder == LSBFIRST)
|
||||||
|
value |= digitalRead(dataPin) << i;
|
||||||
|
else
|
||||||
|
value |= digitalRead(dataPin) << (7 - i);
|
||||||
|
digitalWrite(clockPin, LOW);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (bitOrder == LSBFIRST)
|
||||||
|
digitalWrite(dataPin, !!(val & (1 << i)));
|
||||||
|
else
|
||||||
|
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
|
||||||
|
|
||||||
|
digitalWrite(clockPin, HIGH);
|
||||||
|
digitalWrite(clockPin, LOW);
|
||||||
|
}
|
||||||
|
}
|
6
hardware/digistump/avr/cores/tiny/Arduino.h
Normal file
6
hardware/digistump/avr/cores/tiny/Arduino.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef Arduino_h
|
||||||
|
#define Arduino_h
|
||||||
|
|
||||||
|
#include <WProgram.h>
|
||||||
|
|
||||||
|
#endif
|
308
hardware/digistump/avr/cores/tiny/HardwareSerial.cpp
Normal file
308
hardware/digistump/avr/cores/tiny/HardwareSerial.cpp
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
HardwareSerial.cpp - Hardware serial library for Wiring
|
||||||
|
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 23 November 2006 by David A. Mellis
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "wiring.h"
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
// this next line disables the entire HardwareSerial.cpp,
|
||||||
|
// this is so I can support Attiny series and any other chip without a uart
|
||||||
|
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)
|
||||||
|
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
|
||||||
|
// Define constants and variables for buffering incoming serial data. We're
|
||||||
|
// using a ring buffer (I think), in which rx_buffer_head is the index of the
|
||||||
|
// location to which to write the next incoming character and rx_buffer_tail
|
||||||
|
// is the index of the location from which to read.
|
||||||
|
#if (RAMEND < 1000)
|
||||||
|
#define RX_BUFFER_SIZE 32
|
||||||
|
#else
|
||||||
|
#define RX_BUFFER_SIZE 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ring_buffer
|
||||||
|
{
|
||||||
|
unsigned char buffer[RX_BUFFER_SIZE];
|
||||||
|
int head;
|
||||||
|
int tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(UBRRH) || defined(UBRR0H)
|
||||||
|
ring_buffer rx_buffer = { { 0 }, 0, 0 };
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR1H)
|
||||||
|
ring_buffer rx_buffer1 = { { 0 }, 0, 0 };
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR2H)
|
||||||
|
ring_buffer rx_buffer2 = { { 0 }, 0, 0 };
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR3H)
|
||||||
|
ring_buffer rx_buffer3 = { { 0 }, 0, 0 };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void store_char(unsigned char c, ring_buffer *rx_buffer)
|
||||||
|
{
|
||||||
|
int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE;
|
||||||
|
|
||||||
|
// if we should be storing the received character into the location
|
||||||
|
// just before the tail (meaning that the head would advance to the
|
||||||
|
// current location of the tail), we're about to overflow the buffer
|
||||||
|
// and so we don't write the character or advance the head.
|
||||||
|
if (i != rx_buffer->tail) {
|
||||||
|
rx_buffer->buffer[rx_buffer->head] = c;
|
||||||
|
rx_buffer->head = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USART_RX_vect)
|
||||||
|
SIGNAL(USART_RX_vect)
|
||||||
|
{
|
||||||
|
#if defined(UDR0)
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
#elif defined(UDR)
|
||||||
|
unsigned char c = UDR; // atmega8535
|
||||||
|
#else
|
||||||
|
#error UDR not defined
|
||||||
|
#endif
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_USART0_RECV) && defined(UDR0)
|
||||||
|
SIGNAL(SIG_USART0_RECV)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_UART0_RECV) && defined(UDR0)
|
||||||
|
SIGNAL(SIG_UART0_RECV)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
//#elif defined(SIG_USART_RECV)
|
||||||
|
#elif defined(USART0_RX_vect)
|
||||||
|
// fixed by Mark Sproul this is on the 644/644p
|
||||||
|
//SIGNAL(SIG_USART_RECV)
|
||||||
|
SIGNAL(USART0_RX_vect)
|
||||||
|
{
|
||||||
|
#if defined(UDR0)
|
||||||
|
unsigned char c = UDR0;
|
||||||
|
#elif defined(UDR)
|
||||||
|
unsigned char c = UDR; // atmega8, atmega32
|
||||||
|
#else
|
||||||
|
#error UDR not defined
|
||||||
|
#endif
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_UART_RECV)
|
||||||
|
// this is for atmega8
|
||||||
|
SIGNAL(SIG_UART_RECV)
|
||||||
|
{
|
||||||
|
#if defined(UDR0)
|
||||||
|
unsigned char c = UDR0; // atmega645
|
||||||
|
#elif defined(UDR)
|
||||||
|
unsigned char c = UDR; // atmega8
|
||||||
|
#endif
|
||||||
|
store_char(c, &rx_buffer);
|
||||||
|
}
|
||||||
|
#elif defined(USBCON)
|
||||||
|
#warning No interrupt handler for usart 0
|
||||||
|
#warning Serial(0) is on USB interface
|
||||||
|
#else
|
||||||
|
#error No interrupt handler for usart 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#if defined(SIG_USART1_RECV)
|
||||||
|
#if defined(USART1_RX_vect)
|
||||||
|
//SIGNAL(SIG_USART1_RECV)
|
||||||
|
SIGNAL(USART1_RX_vect)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR1;
|
||||||
|
store_char(c, &rx_buffer1);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_USART1_RECV)
|
||||||
|
#error SIG_USART1_RECV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USART2_RX_vect) && defined(UDR2)
|
||||||
|
SIGNAL(USART2_RX_vect)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR2;
|
||||||
|
store_char(c, &rx_buffer2);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_USART2_RECV)
|
||||||
|
#error SIG_USART2_RECV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USART3_RX_vect) && defined(UDR3)
|
||||||
|
SIGNAL(USART3_RX_vect)
|
||||||
|
{
|
||||||
|
unsigned char c = UDR3;
|
||||||
|
store_char(c, &rx_buffer3);
|
||||||
|
}
|
||||||
|
#elif defined(SIG_USART3_RECV)
|
||||||
|
#error SIG_USART3_RECV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
|
||||||
|
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
|
||||||
|
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
|
||||||
|
volatile uint8_t *udr,
|
||||||
|
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x)
|
||||||
|
{
|
||||||
|
_rx_buffer = rx_buffer;
|
||||||
|
_ubrrh = ubrrh;
|
||||||
|
_ubrrl = ubrrl;
|
||||||
|
_ucsra = ucsra;
|
||||||
|
_ucsrb = ucsrb;
|
||||||
|
_udr = udr;
|
||||||
|
_rxen = rxen;
|
||||||
|
_txen = txen;
|
||||||
|
_rxcie = rxcie;
|
||||||
|
_udre = udre;
|
||||||
|
_u2x = u2x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void HardwareSerial::begin(long baud)
|
||||||
|
{
|
||||||
|
uint16_t baud_setting;
|
||||||
|
bool use_u2x = true;
|
||||||
|
|
||||||
|
#if F_CPU == 16000000UL
|
||||||
|
// hardcoded exception for compatibility with the bootloader shipped
|
||||||
|
// with the Duemilanove and previous boards and the firmware on the 8U2
|
||||||
|
// on the Uno and Mega 2560.
|
||||||
|
if (baud == 57600) {
|
||||||
|
use_u2x = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (use_u2x) {
|
||||||
|
*_ucsra = 1 << _u2x;
|
||||||
|
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||||
|
} else {
|
||||||
|
*_ucsra = 0;
|
||||||
|
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
||||||
|
*_ubrrh = baud_setting >> 8;
|
||||||
|
*_ubrrl = baud_setting;
|
||||||
|
|
||||||
|
sbi(*_ucsrb, _rxen);
|
||||||
|
sbi(*_ucsrb, _txen);
|
||||||
|
sbi(*_ucsrb, _rxcie);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::end()
|
||||||
|
{
|
||||||
|
cbi(*_ucsrb, _rxen);
|
||||||
|
cbi(*_ucsrb, _txen);
|
||||||
|
cbi(*_ucsrb, _rxcie);
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::available(void)
|
||||||
|
{
|
||||||
|
return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::peek(void)
|
||||||
|
{
|
||||||
|
if (_rx_buffer->head == _rx_buffer->tail) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return _rx_buffer->buffer[_rx_buffer->tail];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int HardwareSerial::read(void)
|
||||||
|
{
|
||||||
|
// if the head isn't ahead of the tail, we don't have any characters
|
||||||
|
if (_rx_buffer->head == _rx_buffer->tail) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
|
||||||
|
_rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HardwareSerial::flush()
|
||||||
|
{
|
||||||
|
// don't reverse this or there may be problems if the RX interrupt
|
||||||
|
// occurs after reading the value of rx_buffer_head but before writing
|
||||||
|
// the value to rx_buffer_tail; the previous value of rx_buffer_head
|
||||||
|
// may be written to rx_buffer_tail, making it appear as if the buffer
|
||||||
|
// don't reverse this or there may be problems if the RX interrupt
|
||||||
|
// occurs after reading the value of rx_buffer_head but before writing
|
||||||
|
// the value to rx_buffer_tail; the previous value of rx_buffer_head
|
||||||
|
// may be written to rx_buffer_tail, making it appear as if the buffer
|
||||||
|
// were full, not empty.
|
||||||
|
_rx_buffer->head = _rx_buffer->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HardwareSerial::write(uint8_t c)
|
||||||
|
{
|
||||||
|
while (!((*_ucsra) & (1 << _udre)))
|
||||||
|
;
|
||||||
|
|
||||||
|
*_udr = c;
|
||||||
|
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if ! DEFAULT_TO_TINY_DEBUG_SERIAL
|
||||||
|
#if defined(UBRRH) && defined(UBRRL)
|
||||||
|
HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);
|
||||||
|
#elif defined(UBRR0H) && defined(UBRR0L)
|
||||||
|
HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0);
|
||||||
|
#elif defined(USBCON)
|
||||||
|
#warning no serial port defined (port 0)
|
||||||
|
#else
|
||||||
|
#error no serial port defined (port 0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(UBRR1H)
|
||||||
|
HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1);
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR2H)
|
||||||
|
HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2);
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR3H)
|
||||||
|
HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // whole file
|
77
hardware/digistump/avr/cores/tiny/HardwareSerial.h
Normal file
77
hardware/digistump/avr/cores/tiny/HardwareSerial.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
HardwareSerial.h - Hardware serial library for Wiring
|
||||||
|
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 28 September 2010 by Mark Sproul
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HardwareSerial_h
|
||||||
|
#define HardwareSerial_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
struct ring_buffer;
|
||||||
|
|
||||||
|
class HardwareSerial : public Stream
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ring_buffer *_rx_buffer;
|
||||||
|
volatile uint8_t *_ubrrh;
|
||||||
|
volatile uint8_t *_ubrrl;
|
||||||
|
volatile uint8_t *_ucsra;
|
||||||
|
volatile uint8_t *_ucsrb;
|
||||||
|
volatile uint8_t *_udr;
|
||||||
|
uint8_t _rxen;
|
||||||
|
uint8_t _txen;
|
||||||
|
uint8_t _rxcie;
|
||||||
|
uint8_t _udre;
|
||||||
|
uint8_t _u2x;
|
||||||
|
public:
|
||||||
|
HardwareSerial(ring_buffer *rx_buffer,
|
||||||
|
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
|
||||||
|
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
|
||||||
|
volatile uint8_t *udr,
|
||||||
|
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x);
|
||||||
|
void begin(long);
|
||||||
|
void end();
|
||||||
|
virtual int available(void);
|
||||||
|
virtual int peek(void);
|
||||||
|
virtual int read(void);
|
||||||
|
virtual void flush(void);
|
||||||
|
virtual size_t write(uint8_t);
|
||||||
|
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||||
|
};
|
||||||
|
|
||||||
|
#if (defined(UBRRH) || defined(UBRR0H)) && ! DEFAULT_TO_TINY_DEBUG_SERIAL
|
||||||
|
extern HardwareSerial Serial;
|
||||||
|
#elif defined(USBCON)
|
||||||
|
#include "usb_api.h"
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR1H)
|
||||||
|
extern HardwareSerial Serial1;
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR2H)
|
||||||
|
extern HardwareSerial Serial2;
|
||||||
|
#endif
|
||||||
|
#if defined(UBRR3H)
|
||||||
|
extern HardwareSerial Serial3;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
247
hardware/digistump/avr/cores/tiny/Print.cpp
Normal file
247
hardware/digistump/avr/cores/tiny/Print.cpp
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
Print.cpp - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 23 November 2006 by David A. Mellis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "wiring.h"
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* default implementation: may be overridden */
|
||||||
|
void Print::write(const char *str)
|
||||||
|
{
|
||||||
|
while (*str)
|
||||||
|
write(*str++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default implementation: may be overridden */
|
||||||
|
void Print::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
while (size--)
|
||||||
|
write(*buffer++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(const String &s)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
write(s[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(const char str[])
|
||||||
|
{
|
||||||
|
write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(char c, int base)
|
||||||
|
{
|
||||||
|
print((long) c, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
print((unsigned long) b, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(int n, int base)
|
||||||
|
{
|
||||||
|
print((long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(unsigned int n, int base)
|
||||||
|
{
|
||||||
|
print((unsigned long) n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(long n, int base)
|
||||||
|
{
|
||||||
|
if (base == 0) {
|
||||||
|
write(n);
|
||||||
|
} else if (base == 10) {
|
||||||
|
if (n < 0) {
|
||||||
|
print('-');
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
printNumber(n, 10);
|
||||||
|
} else {
|
||||||
|
printNumber(n, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(unsigned long n, int base)
|
||||||
|
{
|
||||||
|
if (base == 0) write(n);
|
||||||
|
else printNumber(n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::print(double n, int digits)
|
||||||
|
{
|
||||||
|
printFloat(n, digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Print::print( fstr_t* s )
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
ch = pgm_read_byte( s );
|
||||||
|
while ( ch != 0 )
|
||||||
|
{
|
||||||
|
write( ch );
|
||||||
|
++s;
|
||||||
|
++rv;
|
||||||
|
ch = pgm_read_byte( s );
|
||||||
|
}
|
||||||
|
return( rv );
|
||||||
|
}
|
||||||
|
|
||||||
|
int Print::println(void)
|
||||||
|
{
|
||||||
|
print('\r');
|
||||||
|
print('\n');
|
||||||
|
return( 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(const String &s)
|
||||||
|
{
|
||||||
|
print(s);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(const char c[])
|
||||||
|
{
|
||||||
|
print(c);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(char c, int base)
|
||||||
|
{
|
||||||
|
print(c, base);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(unsigned char b, int base)
|
||||||
|
{
|
||||||
|
print(b, base);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(int n, int base)
|
||||||
|
{
|
||||||
|
print(n, base);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(unsigned int n, int base)
|
||||||
|
{
|
||||||
|
print(n, base);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(long n, int base)
|
||||||
|
{
|
||||||
|
print(n, base);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(unsigned long n, int base)
|
||||||
|
{
|
||||||
|
print(n, base);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::println(double n, int digits)
|
||||||
|
{
|
||||||
|
print(n, digits);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Print::println( fstr_t* s )
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = print( s );
|
||||||
|
rv += println();
|
||||||
|
return( rv );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Methods /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Print::printNumber(unsigned long n, uint8_t base)
|
||||||
|
{
|
||||||
|
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||||
|
unsigned long i = 0;
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
print('0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n > 0) {
|
||||||
|
buf[i++] = n % base;
|
||||||
|
n /= base;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i > 0; i--)
|
||||||
|
print((char) (buf[i - 1] < 10 ?
|
||||||
|
'0' + buf[i - 1] :
|
||||||
|
'A' + buf[i - 1] - 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print::printFloat(double number, uint8_t digits)
|
||||||
|
{
|
||||||
|
// Handle negative numbers
|
||||||
|
if (number < 0.0)
|
||||||
|
{
|
||||||
|
print('-');
|
||||||
|
number = -number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||||
|
double rounding = 0.5;
|
||||||
|
for (uint8_t i=0; i<digits; ++i)
|
||||||
|
rounding /= 10.0;
|
||||||
|
|
||||||
|
number += rounding;
|
||||||
|
|
||||||
|
// Extract the integer part of the number and print it
|
||||||
|
unsigned long int_part = (unsigned long)number;
|
||||||
|
double remainder = number - (double)int_part;
|
||||||
|
print(int_part);
|
||||||
|
|
||||||
|
// Print the decimal point, but only if there are digits beyond
|
||||||
|
if (digits > 0)
|
||||||
|
print(".");
|
||||||
|
|
||||||
|
// Extract digits from the remainder one at a time
|
||||||
|
while (digits-- > 0)
|
||||||
|
{
|
||||||
|
remainder *= 10.0;
|
||||||
|
int toPrint = int(remainder);
|
||||||
|
print(toPrint);
|
||||||
|
remainder -= toPrint;
|
||||||
|
}
|
||||||
|
}
|
108
hardware/digistump/avr/cores/tiny/Print.h
Normal file
108
hardware/digistump/avr/cores/tiny/Print.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
Print.h - Base class that provides print() and println()
|
||||||
|
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Modified 20-11-2010 by B.Cook ...
|
||||||
|
|
||||||
|
http://arduiniana.org/libraries/flash/
|
||||||
|
Printable support thanks to Mikal Hart
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Print_h
|
||||||
|
#define Print_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h> // for size_t
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include "WString.h"
|
||||||
|
|
||||||
|
#define DEC 10
|
||||||
|
#define HEX 16
|
||||||
|
#define OCT 8
|
||||||
|
#define BIN 2
|
||||||
|
#define BYTE 0
|
||||||
|
|
||||||
|
#define ARDUINO_CORE_PRINTABLE_SUPPORT
|
||||||
|
|
||||||
|
class Print;
|
||||||
|
|
||||||
|
/* Printable...*/
|
||||||
|
|
||||||
|
class _Printable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void print(Print &stream) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ...Printable */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
}
|
||||||
|
fstr_t;
|
||||||
|
|
||||||
|
/* rmv: Use the macro below in preparation for the next Arduino release.
|
||||||
|
# define FSTR(s) ((fstr_t*)PSTR(s))
|
||||||
|
*/
|
||||||
|
# define F(s) ((fstr_t*)PSTR(s))
|
||||||
|
|
||||||
|
class Print
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void printNumber(unsigned long, uint8_t);
|
||||||
|
void printFloat(double, uint8_t);
|
||||||
|
protected:
|
||||||
|
void setWriteError(int err = 1) { /*write_error = err;*/ }
|
||||||
|
public:
|
||||||
|
virtual size_t write(uint8_t) = 0;
|
||||||
|
virtual void write(const char *str);
|
||||||
|
virtual void write(const uint8_t *buffer, size_t size);
|
||||||
|
|
||||||
|
void print(const String &);
|
||||||
|
void print(const char[]);
|
||||||
|
void print(char, int = BYTE);
|
||||||
|
void print(unsigned char, int = BYTE);
|
||||||
|
void print(int, int = DEC);
|
||||||
|
void print(unsigned int, int = DEC);
|
||||||
|
void print(long, int = DEC);
|
||||||
|
void print(unsigned long, int = DEC);
|
||||||
|
void print(double, int = 2);
|
||||||
|
int print( fstr_t* );
|
||||||
|
|
||||||
|
void println(const String &s);
|
||||||
|
void println(const char[]);
|
||||||
|
void println(char, int = BYTE);
|
||||||
|
void println(unsigned char, int = BYTE);
|
||||||
|
void println(int, int = DEC);
|
||||||
|
void println(unsigned int, int = DEC);
|
||||||
|
void println(long, int = DEC);
|
||||||
|
void println(unsigned long, int = DEC);
|
||||||
|
void println(double, int = 2);
|
||||||
|
int println( fstr_t* );
|
||||||
|
int println(void);
|
||||||
|
public:
|
||||||
|
/* Printable...*/
|
||||||
|
void println(const _Printable &obj)
|
||||||
|
{ obj.print(*this); println(); }
|
||||||
|
void print(const _Printable &obj)
|
||||||
|
{ obj.print(*this); };
|
||||||
|
/* ...Printable */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
65
hardware/digistump/avr/cores/tiny/PwmTimer.h
Normal file
65
hardware/digistump/avr/cores/tiny/PwmTimer.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
PwmTimer.h - Veneer for the PWM timers.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef PwmTimer_h
|
||||||
|
#define PwmTimer_h
|
||||||
|
|
||||||
|
#include "core_pins.h"
|
||||||
|
#include "core_timers.h"
|
||||||
|
|
||||||
|
#define PwmTimer3_(t,f,c) TIMER_PASTE_CHANNEL_A( Timer, t, f, c )
|
||||||
|
#define PwmTimer2_(t,f) TIMER_PASTE_A( Timer, t, f )
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 1
|
||||||
|
#define Pwm0_SetCompareOutputMode PwmTimer3_( CORE_PWM0_TIMER, SetCompareOutputMode, CORE_PWM0_CHANNEL )
|
||||||
|
#define Pwm0_Disconnected PwmTimer2_( CORE_PWM0_TIMER, Disconnected )
|
||||||
|
#define Pwm0_Clear PwmTimer2_( CORE_PWM0_TIMER, Clear )
|
||||||
|
#define Pwm0_SetOutputCompareMatch PwmTimer3_( CORE_PWM0_TIMER, SetOutputCompareMatch, CORE_PWM0_CHANNEL )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 2
|
||||||
|
#define Pwm1_SetCompareOutputMode PwmTimer3_( CORE_PWM1_TIMER, SetCompareOutputMode, CORE_PWM1_CHANNEL )
|
||||||
|
#define Pwm1_Disconnected PwmTimer2_( CORE_PWM1_TIMER, Disconnected )
|
||||||
|
#define Pwm1_Clear PwmTimer2_( CORE_PWM1_TIMER, Clear )
|
||||||
|
#define Pwm1_SetOutputCompareMatch PwmTimer3_( CORE_PWM1_TIMER, SetOutputCompareMatch, CORE_PWM1_CHANNEL )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 3
|
||||||
|
#define Pwm2_SetCompareOutputMode PwmTimer3_( CORE_PWM2_TIMER, SetCompareOutputMode, CORE_PWM2_CHANNEL )
|
||||||
|
#define Pwm2_Disconnected PwmTimer2_( CORE_PWM2_TIMER, Disconnected )
|
||||||
|
#define Pwm2_Clear PwmTimer2_( CORE_PWM2_TIMER, Clear )
|
||||||
|
#define Pwm2_SetOutputCompareMatch PwmTimer3_( CORE_PWM2_TIMER, SetOutputCompareMatch, CORE_PWM2_CHANNEL )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 4
|
||||||
|
#define Pwm3_SetCompareOutputMode PwmTimer3_( CORE_PWM3_TIMER, SetCompareOutputMode, CORE_PWM3_CHANNEL )
|
||||||
|
#define Pwm3_Disconnected PwmTimer2_( CORE_PWM3_TIMER, Disconnected )
|
||||||
|
#define Pwm3_Clear PwmTimer2_( CORE_PWM3_TIMER, Clear )
|
||||||
|
#define Pwm3_SetOutputCompareMatch PwmTimer3_( CORE_PWM3_TIMER, SetOutputCompareMatch, CORE_PWM3_CHANNEL )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 5
|
||||||
|
#error Only 4 pins PWM are supported. Add more macro defintions.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
35
hardware/digistump/avr/cores/tiny/Stream.h
Normal file
35
hardware/digistump/avr/cores/tiny/Stream.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Stream.h - base class for character-based streams.
|
||||||
|
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Stream_h
|
||||||
|
#define Stream_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
class Stream : public Print
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int available() = 0;
|
||||||
|
virtual int read() = 0;
|
||||||
|
virtual int peek() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
42
hardware/digistump/avr/cores/tiny/TinyDebugSerial.cpp
Normal file
42
hardware/digistump/avr/cores/tiny/TinyDebugSerial.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
TinyDebugSerial.cpp - Tiny write-only software serial.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "TinyDebugSerial.h"
|
||||||
|
|
||||||
|
static TinyDebugSerialWriter stub;
|
||||||
|
|
||||||
|
void TinyDebugSerial::useStub( void )
|
||||||
|
{
|
||||||
|
_writer = &stub;
|
||||||
|
_writer->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
TinyDebugSerial::TinyDebugSerial( void )
|
||||||
|
{
|
||||||
|
useStub();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined( DEFAULT_TO_TINY_DEBUG_SERIAL ) && DEFAULT_TO_TINY_DEBUG_SERIAL
|
||||||
|
TinyDebugSerial Serial;
|
||||||
|
#endif
|
749
hardware/digistump/avr/cores/tiny/TinyDebugSerial.h
Normal file
749
hardware/digistump/avr/cores/tiny/TinyDebugSerial.h
Normal file
@ -0,0 +1,749 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
TinyDebugSerial.h - Tiny write-only software serial.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef TinyDebugSerial_h
|
||||||
|
#define TinyDebugSerial_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "binary.h"
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
|
||||||
|
class TinyDebugSerialWriter;
|
||||||
|
class TinyDebugSerial;
|
||||||
|
|
||||||
|
|
||||||
|
class TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class TinyDebugSerial;
|
||||||
|
};
|
||||||
|
|
||||||
|
void TinyDebugSerialWriterInternalBug( void ) __attribute__((error("Serial (TinyDebugSerial) has an internal problem. Contact the developer.")));
|
||||||
|
|
||||||
|
__attribute__((always_inline, unused)) static inline void TinyDebugSerialWriterBangOneByte( uint8_t value, uint8_t SER_REG, uint8_t SER_BIT, uint8_t lom, uint8_t him, uint8_t oloops, uint8_t iloops, uint8_t nops )
|
||||||
|
{
|
||||||
|
if ( __builtin_constant_p( SER_REG )
|
||||||
|
&& __builtin_constant_p( SER_BIT )
|
||||||
|
&& __builtin_constant_p( lom )
|
||||||
|
&& __builtin_constant_p( him )
|
||||||
|
&& __builtin_constant_p( oloops )
|
||||||
|
&& __builtin_constant_p( iloops )
|
||||||
|
&& __builtin_constant_p( nops ) )
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t j;
|
||||||
|
uint8_t ol;
|
||||||
|
uint8_t il;
|
||||||
|
uint8_t b; // Initialized to the low bits
|
||||||
|
uint8_t hib;
|
||||||
|
uint8_t m;
|
||||||
|
|
||||||
|
b = ((value << 1) & 0x1F);
|
||||||
|
hib = ((value >> 4) & 0x1F) | 0x10;
|
||||||
|
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"ldi %[j], 2" "\n\t"
|
||||||
|
"ldi %[i], 5" "\n\t"
|
||||||
|
"ldi %[m], %[lom]" "\n\t"
|
||||||
|
|
||||||
|
// Note: 8 MHz, 9600 baud ---> disabling interrupts does not appear to be necessary
|
||||||
|
|
||||||
|
"cli" "\n\t"
|
||||||
|
|
||||||
|
"rjmp L%=ntop" "\n\t"
|
||||||
|
|
||||||
|
"L%=btop: "
|
||||||
|
"nop" "\n\t" // ---> 7
|
||||||
|
"nop" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
|
||||||
|
"L%=ntop: "
|
||||||
|
"ror %[b]" "\n\t" // ---> 1
|
||||||
|
|
||||||
|
"brcs L%=bxh" "\n\t" // 1 (not taken)
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" // 2
|
||||||
|
"rjmp L%=bxz" "\n\t" // 2
|
||||||
|
|
||||||
|
"L%=bxh: " // 2 (taken)
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" // 2
|
||||||
|
"nop" "\n\t" // 1
|
||||||
|
|
||||||
|
// ---> 5
|
||||||
|
"L%=bxz: "
|
||||||
|
|
||||||
|
"ror %[m]" "\n\t" // ---> 3 or 4
|
||||||
|
"brcc L%=bnoe" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
"L%=bnoe: "
|
||||||
|
|
||||||
|
// ---> 1
|
||||||
|
".if %[oloops] >= 1" "\n\t" // if oloops >= 1 then...
|
||||||
|
"ldi %[ol], %[oloops]" "\n\t" // 4*oloops + oloops*(3*iloops) or oloops*((3*iloops)+4)
|
||||||
|
"L%=odelay: " "\n\t"
|
||||||
|
".endif" "\n\t"
|
||||||
|
"ldi %[il], %[iloops]" "\n\t" // if oloops == 0 then...
|
||||||
|
"L%=idelay: " "\n\t" // (3*iloops)
|
||||||
|
"dec %[il]" "\n\t"
|
||||||
|
"brne L%=idelay" "\n\t"
|
||||||
|
"nop" "\n\t"
|
||||||
|
".if %[oloops] >= 1" "\n\t"
|
||||||
|
"dec %[ol]" "\n\t"
|
||||||
|
"brne L%=odelay" "\n\t"
|
||||||
|
"nop" "\n\t"
|
||||||
|
".endif" "\n\t"
|
||||||
|
|
||||||
|
".if %[nops] >= 1" "\n\t"
|
||||||
|
"nop" "\n\t" //
|
||||||
|
".endif" "\n\t"
|
||||||
|
".if %[nops] >= 2" "\n\t"
|
||||||
|
"nop" "\n\t" //
|
||||||
|
".endif" "\n\t"
|
||||||
|
|
||||||
|
"dec %[i]" "\n\t" // ---> 3
|
||||||
|
"brne L%=btop" "\n\t" //
|
||||||
|
"nop" "\n\t" //
|
||||||
|
|
||||||
|
"dec %[j]" "\n\t" // ---> 7
|
||||||
|
"breq L%=bfin" "\n\t" //
|
||||||
|
"ldi %[i], 5" "\n\t" //
|
||||||
|
"mov %[b], %[hib]" "\n\t" //
|
||||||
|
"ldi %[m], %[him]" "\n\t" //
|
||||||
|
"rjmp L%=ntop" "\n\t" //
|
||||||
|
|
||||||
|
"L%=bfin: "
|
||||||
|
|
||||||
|
"sei" "\n\t"
|
||||||
|
:
|
||||||
|
[i] "=&r" ( i ),
|
||||||
|
[j] "=&r" ( j ),
|
||||||
|
[ol] "=&r" ( ol ),
|
||||||
|
[il] "=&r" ( il ),
|
||||||
|
[m] "=&r" ( m )
|
||||||
|
:
|
||||||
|
[b] "r" ( b ),
|
||||||
|
[hib] "r" ( hib ),
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "M" ( SER_BIT ),
|
||||||
|
[lom] "M" ( lom ),
|
||||||
|
[him] "M" ( him ),
|
||||||
|
[oloops] "M" ( oloops ),
|
||||||
|
[iloops] "M" ( iloops ),
|
||||||
|
[nops] "M" ( nops )
|
||||||
|
:
|
||||||
|
"r31",
|
||||||
|
"r30"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterInternalBug();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_1_9600 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B00100, B00010, 0, 28, 2 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_1_38400 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B00000, B00000, 0, 2, 0 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_1_115200 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"cli" "\n\t"
|
||||||
|
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- 0 */
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b0h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- st is 9 cycles */
|
||||||
|
"rjmp L%=b0z" "\n\t" /* 2 */
|
||||||
|
"L%=b0h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- st is 9 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b0z: "
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b1h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b0 is 8 cycles */
|
||||||
|
"rjmp L%=b1z" "\n\t" /* 2 */
|
||||||
|
"L%=b1h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b0 is 8 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b1z: "
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b2h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b1 is 9 cycles */
|
||||||
|
"rjmp L%=b2z" "\n\t" /* 2 */
|
||||||
|
"L%=b2h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b1 is 9 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b2z: "
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b3h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b2 is 9 cycles */
|
||||||
|
"rjmp L%=b3z" "\n\t" /* 2 */
|
||||||
|
"L%=b3h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b2 is 9 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b3z: "
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b4h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b3 is 8 cycles */
|
||||||
|
"rjmp L%=b4z" "\n\t" /* 2 */
|
||||||
|
"L%=b4h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b3 is 8 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b4z: "
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b5h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b4 is 9 cycles */
|
||||||
|
"rjmp L%=b5z" "\n\t" /* 2 */
|
||||||
|
"L%=b5h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b4 is 9 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b5z: "
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b6h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b5 is 9 cycles */
|
||||||
|
"rjmp L%=b6z" "\n\t" /* 2 */
|
||||||
|
"L%=b6h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b5 is 9 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b6z: "
|
||||||
|
"ror %[value]" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"brcs L%=b7h" "\n\t" /* 1 (not taken) */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"cbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b6 is 8 cycles */
|
||||||
|
"rjmp L%=b7z" "\n\t" /* 2 */
|
||||||
|
"L%=b7h: " /* 2 (taken) */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b6 is 8 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"L%=b7z: "
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t" /* 2 <--- b7 is 9 cycles */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
"nop" "\n\t" /* 1 */
|
||||||
|
/* <---sp is 9 cycles */
|
||||||
|
|
||||||
|
"sei" "\n\t"
|
||||||
|
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[value] "r" ( value ),
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_8_9600 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B01001, B00100, 3, 89, 0 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_8_38400 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B01001, B00100, 0, 62, 2 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_8_115200 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B01010, B10100, 0, 16, 1 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_16_9600 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B10110, B11011, 6, 90, 2 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_16_38400 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B10110, B11011, 5, 25, 1 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
uint8_t SER_REG,
|
||||||
|
uint8_t SER_BIT
|
||||||
|
>
|
||||||
|
class TinyDebugSerialWriter_16_115200 : public TinyDebugSerialWriter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void init( void )
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
"sbi %[serreg]-1, %[serbit]" "\n\t"
|
||||||
|
"sbi %[serreg], %[serbit]" "\n\t"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
[serreg] "I" ( SER_REG ),
|
||||||
|
[serbit] "I" ( SER_BIT )
|
||||||
|
:
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write( uint8_t value )
|
||||||
|
{
|
||||||
|
TinyDebugSerialWriterBangOneByte( value, SER_REG, SER_BIT, B11110, B11111, 0, 39, 1 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX313__ )
|
||||||
|
|
||||||
|
#define TINY_DEBUG_SERIAL_REGISTER 0x1B
|
||||||
|
#define TINY_DEBUG_SERIAL_BIT 1
|
||||||
|
|
||||||
|
#elif defined( __AVR_ATtinyX4__ )
|
||||||
|
|
||||||
|
#if F_CPU <= 8000000L
|
||||||
|
// port B bit 0 (PB0)
|
||||||
|
#define TINY_DEBUG_SERIAL_REGISTER 0x18
|
||||||
|
#define TINY_DEBUG_SERIAL_BIT 0
|
||||||
|
#else
|
||||||
|
// port A bit 0 (PA0)
|
||||||
|
#define TINY_DEBUG_SERIAL_REGISTER 0x1B
|
||||||
|
#define TINY_DEBUG_SERIAL_BIT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined( __AVR_ATtinyX5__ )
|
||||||
|
|
||||||
|
#if F_CPU <= 8000000L
|
||||||
|
// port B bit 3 (PB3)
|
||||||
|
#define TINY_DEBUG_SERIAL_REGISTER 0x18
|
||||||
|
#define TINY_DEBUG_SERIAL_BIT 3
|
||||||
|
#else
|
||||||
|
// port B bit 2 (PB2)
|
||||||
|
#define TINY_DEBUG_SERIAL_REGISTER 0x18
|
||||||
|
#define TINY_DEBUG_SERIAL_BIT 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if F_CPU == 1000000L
|
||||||
|
typedef TinyDebugSerialWriter_1_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
|
||||||
|
typedef TinyDebugSerialWriter_1_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
|
||||||
|
typedef TinyDebugSerialWriter_1_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
|
||||||
|
#define TINY_DEBUG_SERIAL_SUPPORTED 1
|
||||||
|
#elif F_CPU == 8000000L
|
||||||
|
typedef TinyDebugSerialWriter_8_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
|
||||||
|
typedef TinyDebugSerialWriter_8_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
|
||||||
|
typedef TinyDebugSerialWriter_8_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
|
||||||
|
#define TINY_DEBUG_SERIAL_SUPPORTED 1
|
||||||
|
#elif F_CPU == 16000000L
|
||||||
|
typedef TinyDebugSerialWriter_16_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
|
||||||
|
typedef TinyDebugSerialWriter_16_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
|
||||||
|
typedef TinyDebugSerialWriter_16_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
|
||||||
|
#define TINY_DEBUG_SERIAL_SUPPORTED 1
|
||||||
|
#elif F_CPU == 16500000L
|
||||||
|
typedef TinyDebugSerialWriter_16_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
|
||||||
|
typedef TinyDebugSerialWriter_16_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
|
||||||
|
typedef TinyDebugSerialWriter_16_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
|
||||||
|
#define TINY_DEBUG_SERIAL_SUPPORTED 1
|
||||||
|
/*
|
||||||
|
9600...
|
||||||
|
6, 90, 2
|
||||||
|
7, 77, 1
|
||||||
|
38400...
|
||||||
|
1, 130, 2
|
||||||
|
5, 25, 1
|
||||||
|
18, 6, 0
|
||||||
|
115200...
|
||||||
|
0, 39, 1
|
||||||
|
1, 38, 0
|
||||||
|
2, 18, 2
|
||||||
|
9, 3, 1
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if TINY_DEBUG_SERIAL_SUPPORTED
|
||||||
|
|
||||||
|
extern TinyDebugSerialWriter_9600 tdsw9600;
|
||||||
|
extern TinyDebugSerialWriter_38400 tdsw38400;
|
||||||
|
extern TinyDebugSerialWriter_115200 tdsw115200;
|
||||||
|
|
||||||
|
void TinyDebugSerialBadBaud( void ) __attribute__((error("Serial (TinyDebugSerial) supports three baud rates: 9600, 38400, or 115200.")));
|
||||||
|
void TinyDebugSerialBaudMustBeConstant( void ) __attribute__((error("The baud rate for Serial (TinyDebugSerial) cannot be changed at run-time. Use 9600, 38400, or 115200.")));
|
||||||
|
|
||||||
|
class TinyDebugSerial : public Stream
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
TinyDebugSerialWriter* _writer;
|
||||||
|
|
||||||
|
void useStub( void );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TinyDebugSerial( void );
|
||||||
|
|
||||||
|
inline void begin( long baud )
|
||||||
|
{
|
||||||
|
if ( __builtin_constant_p( baud ) )
|
||||||
|
{
|
||||||
|
if ( baud == 9600 )
|
||||||
|
{
|
||||||
|
_writer = &tdsw9600;
|
||||||
|
}
|
||||||
|
else if ( baud == 38400 )
|
||||||
|
{
|
||||||
|
_writer = &tdsw38400;
|
||||||
|
}
|
||||||
|
else if ( baud == 115200 )
|
||||||
|
{
|
||||||
|
_writer = &tdsw115200;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TinyDebugSerialBadBaud();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TinyDebugSerialBaudMustBeConstant();
|
||||||
|
}
|
||||||
|
_writer->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void end( void )
|
||||||
|
{
|
||||||
|
useStub();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int available( void )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int peek( void )
|
||||||
|
{
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int read( void )
|
||||||
|
{
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flush( void )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t write( uint8_t c )
|
||||||
|
{
|
||||||
|
_writer->write( c );
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||||
|
};
|
||||||
|
|
||||||
|
#if DEFAULT_TO_TINY_DEBUG_SERIAL
|
||||||
|
extern TinyDebugSerial Serial;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
26
hardware/digistump/avr/cores/tiny/TinyDebugSerial115200.cpp
Normal file
26
hardware/digistump/avr/cores/tiny/TinyDebugSerial115200.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
TinyDebugSerial.cpp - Tiny write-only software serial.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#include "TinyDebugSerial.h"
|
||||||
|
|
||||||
|
TinyDebugSerialWriter_115200 tdsw115200;
|
26
hardware/digistump/avr/cores/tiny/TinyDebugSerial38400.cpp
Normal file
26
hardware/digistump/avr/cores/tiny/TinyDebugSerial38400.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
TinyDebugSerial.cpp - Tiny write-only software serial.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#include "TinyDebugSerial.h"
|
||||||
|
|
||||||
|
TinyDebugSerialWriter_38400 tdsw38400;
|
26
hardware/digistump/avr/cores/tiny/TinyDebugSerial9600.cpp
Normal file
26
hardware/digistump/avr/cores/tiny/TinyDebugSerial9600.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
TinyDebugSerial.cpp - Tiny write-only software serial.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#include "TinyDebugSerial.h"
|
||||||
|
|
||||||
|
TinyDebugSerialWriter_9600 tdsw9600;
|
28
hardware/digistump/avr/cores/tiny/TinyDebugSerialErrors.cpp
Normal file
28
hardware/digistump/avr/cores/tiny/TinyDebugSerialErrors.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
TinyDebugSerial.cpp - Tiny write-only software serial.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#include "TinyDebugSerial.h"
|
||||||
|
|
||||||
|
void TinyDebugSerialWriterInternalBug( void ) { }
|
||||||
|
void TinyDebugSerialBadBaud( void ) { }
|
||||||
|
void TinyDebugSerialBaudMustBeConstant( void ) { }
|
504
hardware/digistump/avr/cores/tiny/Tone.cpp
Normal file
504
hardware/digistump/avr/cores/tiny/Tone.cpp
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
/* Tone.cpp
|
||||||
|
|
||||||
|
A Tone Generator Library
|
||||||
|
|
||||||
|
Written by Brett Hagman
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Version Modified By Date Comments
|
||||||
|
------- ----------- -------- --------
|
||||||
|
0001 B Hagman 09/08/02 Initial coding
|
||||||
|
0002 B Hagman 09/08/18 Multiple pins
|
||||||
|
0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
|
||||||
|
0004 B Hagman 09/09/26 Fixed problems with ATmega8
|
||||||
|
0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
|
||||||
|
09/11/25 Changed pin toggle method to XOR
|
||||||
|
09/11/25 Fixed timer0 from being excluded
|
||||||
|
0006 D Mellis 09/12/29 Replaced objects with functions
|
||||||
|
0007 B Cook 10/05/03 Rewritten to only work with Timer1 and support direct hardware output
|
||||||
|
0008 B Cook 10/05/03 Rewritten so the timer can be selected at compile time
|
||||||
|
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
#define DEBUG_TONE 0
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "ToneTimer.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#include "wiring.h"
|
||||||
|
|
||||||
|
#if (TONETIMER_NUMBER_PRESCALERS != 5) && (TONETIMER_NUMBER_PRESCALERS != 15)
|
||||||
|
#error Only five or fifteen prescalers are supported. Update the code to support the number of actual prescalers.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TONETIMER_NUMBER_PRESCALERS == 15
|
||||||
|
#define TONETIMER_MAXIMUM_DIVISOR ( (unsigned long)(TONETIMER_(PRESCALER_VALUE_15)) * (1L + (unsigned long)(TONETIMER_(MAXIMUM_OCR))) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TONETIMER_NUMBER_PRESCALERS == 5
|
||||||
|
#define TONETIMER_MAXIMUM_DIVISOR ( (unsigned long)(TONETIMER_(PRESCALER_VALUE_5)) * (1L + (unsigned long)(TONETIMER_(MAXIMUM_OCR))) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const unsigned int Tone_Lowest_Frequency = (F_CPU + (2L * TONETIMER_MAXIMUM_DIVISOR - 1L)) / (2L * TONETIMER_MAXIMUM_DIVISOR);
|
||||||
|
|
||||||
|
#if (TONETIMER_(MAXIMUM_OCR) == 65535) && (TONETIMER_(PRESCALE_SET) == 1)
|
||||||
|
#if F_CPU <= 1000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (7)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 8000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (7)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (61)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 16000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (1)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (15)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (122)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 16500000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (1)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (15)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (122)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (TONETIMER_(MAXIMUM_OCR) == 255) && (TONETIMER_(PRESCALE_SET) == 1)
|
||||||
|
#if F_CPU <= 1000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (7)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (30)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (243)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (1949)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 8000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (60)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (243)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (1949)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (15594)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 16000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (121)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (487)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (3898)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (31189)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 16500000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (121)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (487)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (3898)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (31189)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (TONETIMER_(MAXIMUM_OCR) == 255) && (TONETIMER_(PRESCALE_SET) == 2)
|
||||||
|
#if F_CPU <= 1000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_12 (1)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_11 (3)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_10 (7)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_9 (15)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_8 (30)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_7 (60)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_6 (121)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (243)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (487)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (974)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (1949)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 8000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_15 (1)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_14 (3)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_13 (7)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_12 (15)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_11 (30)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_10 (60)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_9 (121)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_8 (243)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_7 (487)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_6 (974)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (1949)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (3898)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (7797)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (15594)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 16000000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_15 (3)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_14 (7)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_13 (15)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_12 (30)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_11 (60)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_10 (121)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_9 (243)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_8 (487)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_7 (974)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_6 (1949)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (3898)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (7797)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (15594)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (31189)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#elif F_CPU <= 16500000
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_15 (3)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_14 (7)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_13 (15)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_12 (30)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_11 (60)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_10 (121)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_9 (243)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_8 (487)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_7 (974)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_6 (1949)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_5 (3898)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_4 (7797)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_3 (15594)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_2 (31189)
|
||||||
|
#define TONE_FREQUENCY_CUTOFF_1 (65535)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG_TONE
|
||||||
|
uint16_t debug_tone_last_OCRxA;
|
||||||
|
uint16_t debug_tone_last_CSV;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// timerx_toggle_count:
|
||||||
|
// > 0 - duration specified
|
||||||
|
// = 0 - stopped
|
||||||
|
// < 0 - infinitely (until stop() method called, or new play() called)
|
||||||
|
|
||||||
|
static volatile long tone_timer_toggle_count;
|
||||||
|
static volatile uint8_t *tone_timer_pin_register;
|
||||||
|
static volatile uint8_t tone_timer_pin_mask;
|
||||||
|
|
||||||
|
static uint8_t tone_pin = 255;
|
||||||
|
|
||||||
|
|
||||||
|
void tone( uint8_t _pin, unsigned int frequency, unsigned long duration )
|
||||||
|
{
|
||||||
|
tonetimer_(ocr_t) ocr;
|
||||||
|
tonetimer_(prescale_value_t) csv;
|
||||||
|
tonetimer_(cs_t) csi;
|
||||||
|
|
||||||
|
if ( tone_pin == 255 )
|
||||||
|
{
|
||||||
|
/* Set the timer to power-up conditions so we start from a known state */
|
||||||
|
ToneTimer_SetToPowerup();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compare Output Mode = Normal port operation, OCxA/OCxB disconnected.
|
||||||
|
Waveform Generation Mode = 4; 0100; CTC; (Clear Timer on Compare); OCR1A; Immediate; MAX
|
||||||
|
Clock Select = No clock source (Timer/Counter stopped).
|
||||||
|
Note: Turn off the clock first to avoid ticks and scratches.
|
||||||
|
*/
|
||||||
|
ToneTimer_SetWaveformGenerationMode( ToneTimer_(CTC_OCR) );
|
||||||
|
|
||||||
|
/* If the tone pin can be driven directly from the timer */
|
||||||
|
|
||||||
|
if ( (_pin == ToneTimer_OutputComparePinA) || (_pin == ToneTimer_OutputComparePinB) )
|
||||||
|
{
|
||||||
|
/* Pin toggling is handled by the hardware */
|
||||||
|
tone_timer_pin_register = NULL;
|
||||||
|
tone_timer_pin_mask = 0;
|
||||||
|
|
||||||
|
if ( _pin == ToneTimer_OutputComparePinA )
|
||||||
|
{
|
||||||
|
/* Compare Output Mode = Toggle OCxA on Compare Match. */
|
||||||
|
ToneTimer_SetCompareOutputModeA( ToneTimer_(Toggle) );
|
||||||
|
}
|
||||||
|
else // if ( _pin == ToneTimer_OutputComparePinB )
|
||||||
|
{
|
||||||
|
/* Compare Output Mode = Toggle OCxA on Compare Match. */
|
||||||
|
ToneTimer_SetCompareOutputModeB( ToneTimer_(Toggle) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Save information needed by the interrupt service routine */
|
||||||
|
tone_timer_pin_register = portOutputRegister( digitalPinToPort( _pin ) );
|
||||||
|
tone_timer_pin_mask = digitalPinToBitMask( _pin );
|
||||||
|
|
||||||
|
/* Compare Output Mode = Normal port operation, OCxA disconnected. */
|
||||||
|
ToneTimer_DisconnectOutputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the pin is configured for output */
|
||||||
|
pinMode( _pin, OUTPUT );
|
||||||
|
|
||||||
|
tone_pin = _pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( tone_pin == _pin )
|
||||||
|
{
|
||||||
|
/* Stop the clock while we make changes. */
|
||||||
|
|
||||||
|
ToneTimer_ClockSelect( ToneTimer_(Stopped) );
|
||||||
|
|
||||||
|
/* Start the counter at zero to reduce ticks and scratches. */
|
||||||
|
|
||||||
|
ToneTimer_SetCount( 0 );
|
||||||
|
|
||||||
|
if ( frequency > 0 )
|
||||||
|
{
|
||||||
|
if ( frequency < Tone_Lowest_Frequency )
|
||||||
|
{
|
||||||
|
frequency = Tone_Lowest_Frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine which prescaler to use */
|
||||||
|
/* Set the Output Compare Register (rounding up) */
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_15 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_15 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_15);
|
||||||
|
csi = ToneTimer_(Prescale_Index_15);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_14 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_14 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_14);
|
||||||
|
csi = ToneTimer_(Prescale_Index_14);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_13 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_13 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_13);
|
||||||
|
csi = ToneTimer_(Prescale_Index_13);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_12 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_12 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_12);
|
||||||
|
csi = ToneTimer_(Prescale_Index_12);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_11 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_11 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_11);
|
||||||
|
csi = ToneTimer_(Prescale_Index_11);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_10 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_10 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_10);
|
||||||
|
csi = ToneTimer_(Prescale_Index_10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_9 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_9 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_9);
|
||||||
|
csi = ToneTimer_(Prescale_Index_9);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_8 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_8 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_8);
|
||||||
|
csi = ToneTimer_(Prescale_Index_8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_7 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_7 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_7);
|
||||||
|
csi = ToneTimer_(Prescale_Index_7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_6 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_6 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_6);
|
||||||
|
csi = ToneTimer_(Prescale_Index_6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_5 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_5 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_5);
|
||||||
|
csi = ToneTimer_(Prescale_Index_5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_4 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_4 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_4);
|
||||||
|
csi = ToneTimer_(Prescale_Index_4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( TONE_FREQUENCY_CUTOFF_3 )
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_3 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_3);
|
||||||
|
csi = ToneTimer_(Prescale_Index_3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( frequency <= TONE_FREQUENCY_CUTOFF_2 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_2);
|
||||||
|
csi = ToneTimer_(Prescale_Index_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else // if ( frequency <= TONE_FREQUENCY_CUTOFF_1 )
|
||||||
|
{
|
||||||
|
csv = TONETIMER_(PRESCALER_VALUE_1);
|
||||||
|
csi = ToneTimer_(Prescale_Index_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ocr = ( (2L * F_CPU) / (frequency * 2L * csv) + 1L ) / 2L - 1L;
|
||||||
|
ToneTimer_SetOutputCompareMatchAndClear( ocr );
|
||||||
|
|
||||||
|
#if DEBUG_TONE
|
||||||
|
debug_tone_last_OCRxA = ocr;
|
||||||
|
debug_tone_last_CSV = csv;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Does the caller want a specific duration? */
|
||||||
|
if ( duration > 0 )
|
||||||
|
{
|
||||||
|
/* Determine how many times the value toggles */
|
||||||
|
tone_timer_toggle_count = (2 * frequency * duration) / 1000;
|
||||||
|
|
||||||
|
/* Output Compare A Match Interrupt Enable */
|
||||||
|
ToneTimer_EnableOutputCompareInterruptA();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Indicate to the interrupt service routine that we'll be running until further notice */
|
||||||
|
tone_timer_toggle_count = -1;
|
||||||
|
|
||||||
|
/* All pins but the OCxA / OCxB pins have to be driven by software */
|
||||||
|
if ( (_pin != ToneTimer_OutputComparePinA) && (_pin != ToneTimer_OutputComparePinB) )
|
||||||
|
{
|
||||||
|
/* Output Compare A Match Interrupt Enable */
|
||||||
|
ToneTimer_EnableOutputCompareInterruptA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the clock... */
|
||||||
|
|
||||||
|
ToneTimer_ClockSelect( csi );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* To be on the safe side, turn off all interrupts */
|
||||||
|
ToneTimer_InterruptsOff();
|
||||||
|
|
||||||
|
/* Clock is stopped. Counter is zero. The only thing left to do is turn off the output. */
|
||||||
|
digitalWrite( _pin, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void noTone( uint8_t _pin )
|
||||||
|
{
|
||||||
|
if ( (tone_pin != 255)
|
||||||
|
&& ((tone_pin == _pin) || (_pin == 255)) )
|
||||||
|
{
|
||||||
|
// Turn off all interrupts
|
||||||
|
ToneTimer_InterruptsOff();
|
||||||
|
|
||||||
|
// Stop the clock while we make changes.
|
||||||
|
ToneTimer_ClockSelect( ToneTimer_(Stopped) );
|
||||||
|
|
||||||
|
// Set the Tone Timer exactly the same as init did...
|
||||||
|
initToneTimer();
|
||||||
|
|
||||||
|
//rmv ToneTimer_SetToPowerup();
|
||||||
|
|
||||||
|
/* rmv
|
||||||
|
// put timer 1 in 8-bit phase correct pwm mode
|
||||||
|
TCCR1A = (0<<COM1A1)|(0<<COM1A0) | (0<<COM1B1)|(0<<COM1B0) | (0<<WGM11)|(1<<WGM10);
|
||||||
|
|
||||||
|
// set timer 1 prescale factor to 64
|
||||||
|
// and start the timer
|
||||||
|
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13)|(0<<WGM12) | (0<<CS12)|(1<<CS11)|(1<<CS10);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set the output low
|
||||||
|
if ( tone_timer_pin_register != NULL )
|
||||||
|
{
|
||||||
|
*tone_timer_pin_register &= ~(tone_timer_pin_mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
digitalWrite( tone_pin, LOW );
|
||||||
|
}
|
||||||
|
|
||||||
|
tone_pin = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ISR( TONETIMER_COMPA_vect, ISR_NOBLOCK )
|
||||||
|
{
|
||||||
|
if ( tone_timer_toggle_count != 0 )
|
||||||
|
{
|
||||||
|
if ( tone_timer_toggle_count > 0 )
|
||||||
|
{
|
||||||
|
--tone_timer_toggle_count;
|
||||||
|
|
||||||
|
if ( tone_timer_toggle_count == 0 )
|
||||||
|
{
|
||||||
|
// Shutdown the hardware
|
||||||
|
noTone( 255 );
|
||||||
|
|
||||||
|
// Skip the rest. We're finished.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*tone_timer_pin_register ^= tone_timer_pin_mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Shutdown the hardware
|
||||||
|
noTone( 255 );
|
||||||
|
}
|
||||||
|
}
|
50
hardware/digistump/avr/cores/tiny/ToneTimer.h
Normal file
50
hardware/digistump/avr/cores/tiny/ToneTimer.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
ToneTimer.h - Veneer for the Tone Timer.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef ToneTimer_h
|
||||||
|
#define ToneTimer_h
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "core_timers.h"
|
||||||
|
|
||||||
|
#define tonetimer_(t) TIMER_PASTE_A( timer, TIMER_TO_USE_FOR_TONE, t )
|
||||||
|
#define ToneTimer_(f) TIMER_PASTE_A( Timer, TIMER_TO_USE_FOR_TONE, f )
|
||||||
|
#define TONETIMER_(c) TIMER_PASTE_A( TIMER, TIMER_TO_USE_FOR_TONE, c )
|
||||||
|
|
||||||
|
#define ToneTimer_SetToPowerup ToneTimer_(SetToPowerup)
|
||||||
|
#define ToneTimer_SetWaveformGenerationMode ToneTimer_(SetWaveformGenerationMode)
|
||||||
|
#define ToneTimer_OutputComparePinA ToneTimer_(OutputComparePinA)
|
||||||
|
#define ToneTimer_OutputComparePinB ToneTimer_(OutputComparePinB)
|
||||||
|
#define ToneTimer_SetCompareOutputModeA ToneTimer_(SetCompareOutputModeA)
|
||||||
|
#define ToneTimer_SetCompareOutputModeB ToneTimer_(SetCompareOutputModeB)
|
||||||
|
#define ToneTimer_DisconnectOutputs ToneTimer_(DisconnectOutputs)
|
||||||
|
#define ToneTimer_ClockSelect ToneTimer_(ClockSelect)
|
||||||
|
#define ToneTimer_SetCount ToneTimer_(SetCount)
|
||||||
|
#define TONETIMER_NUMBER_PRESCALERS TONETIMER_(NUMBER_PRESCALERS)
|
||||||
|
#define ToneTimer_SetOutputCompareMatchAndClear ToneTimer_(SetOutputCompareMatchAndClear)
|
||||||
|
#define ToneTimer_InterruptsOff ToneTimer_(InterruptsOff)
|
||||||
|
#define ToneTimer_EnableOutputCompareInterruptA ToneTimer_(EnableOutputCompareInterruptA)
|
||||||
|
#define TONETIMER_COMPA_vect TONETIMER_(COMPA_vect)
|
||||||
|
#define TONETIMER_SUPPORTS_PHASE_CORRECT_PWM TONETIMER_(SUPPORTS_PHASE_CORRECT_PWM)
|
||||||
|
|
||||||
|
#endif
|
78
hardware/digistump/avr/cores/tiny/UserTimer.h
Normal file
78
hardware/digistump/avr/cores/tiny/UserTimer.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
UserTimer.h - Veneer for the User Timer (same timer as the one used for
|
||||||
|
Tone)
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef UserTimer_h
|
||||||
|
#define UserTimer_h
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "core_timers.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Assume there are only two timers. One for millis and one for everything
|
||||||
|
else.
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if TIMER_TO_USE_FOR_MILLIS == 0
|
||||||
|
#define TIMER_TO_USE_FOR_USER 1
|
||||||
|
#elif TIMER_TO_USE_FOR_MILLIS == 1
|
||||||
|
#define TIMER_TO_USE_FOR_USER 0
|
||||||
|
#else
|
||||||
|
#error Unexpected condition in UserTimer.h.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Macros to help generate the macros below
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#define usertimer_(t) TIMER_PASTE_A( timer, TIMER_TO_USE_FOR_USER, t )
|
||||||
|
#define UserTimer_(f) TIMER_PASTE_A( Timer, TIMER_TO_USE_FOR_USER, f )
|
||||||
|
#define USERTIMER_(c) TIMER_PASTE_A( TIMER, TIMER_TO_USE_FOR_USER, c )
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Macros to provide a veneer over the data-types, functions, and constants in
|
||||||
|
core_timers.h
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#define UserTimer_SetToPowerup UserTimer_(SetToPowerup)
|
||||||
|
#define UserTimer_InterruptsOff UserTimer_(InterruptsOff)
|
||||||
|
#define UserTimer_ClockSelect UserTimer_(ClockSelect)
|
||||||
|
#define UserTimer_SetWaveformGenerationMode UserTimer_(SetWaveformGenerationMode)
|
||||||
|
#define UserTimer_SetCompareOutputModeA UserTimer_(SetCompareOutputModeA)
|
||||||
|
#define UserTimer_SetCompareOutputModeB UserTimer_(SetCompareOutputModeB)
|
||||||
|
#define UserTimer_SetOutputCompareMatchAndClear UserTimer_(SetOutputCompareMatchAndClear)
|
||||||
|
#define UserTimer_EnableOutputCompareInterruptA UserTimer_(EnableOutputCompareInterruptA)
|
||||||
|
#define UserTimer_EnableOverflowInterrupt UserTimer_(EnableOverflowInterrupt)
|
||||||
|
#define UserTimer_GetCount UserTimer_(GetCount)
|
||||||
|
#define UserTimer_SetCount UserTimer_(SetCount)
|
||||||
|
#define UserTimer_IsOverflowSet UserTimer_(IsOverflowSet)
|
||||||
|
|
||||||
|
#define USERTIMER_OVF_vect USERTIMER_(OVF_vect)
|
||||||
|
#define USERTIMER_COMPA_vect USERTIMER_(COMPA_vect)
|
||||||
|
#define USERTIMER_COMPB_vect USERTIMER_(COMPB_vect)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
168
hardware/digistump/avr/cores/tiny/WCharacter.h
Normal file
168
hardware/digistump/avr/cores/tiny/WCharacter.h
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
WCharacter.h - Character utility functions for Wiring & Arduino
|
||||||
|
Copyright (c) 2010 Hernando Barragan. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Character_h
|
||||||
|
#define Character_h
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
// WCharacter.h prototypes
|
||||||
|
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isAlpha(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isAscii(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isWhitespace(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isControl(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isDigit(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isGraph(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isLowerCase(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isPrintable(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isPunct(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isSpace(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isUpperCase(int c) __attribute__((always_inline));
|
||||||
|
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||||
|
inline int toAscii(int c) __attribute__((always_inline));
|
||||||
|
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||||
|
inline int toUpperCase(int c)__attribute__((always_inline));
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an alphanumeric character.
|
||||||
|
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||||
|
inline boolean isAlphaNumeric(int c)
|
||||||
|
{
|
||||||
|
return ( isalnum(c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an alphabetic character.
|
||||||
|
// It is equivalent to (isupper(c) || islower(c)).
|
||||||
|
inline boolean isAlpha(int c)
|
||||||
|
{
|
||||||
|
return ( isalpha(c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks whether c is a 7-bit unsigned char value
|
||||||
|
// that fits into the ASCII character set.
|
||||||
|
inline boolean isAscii(int c)
|
||||||
|
{
|
||||||
|
return ( isascii (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a blank character, that is, a space or a tab.
|
||||||
|
inline boolean isWhitespace(int c)
|
||||||
|
{
|
||||||
|
return ( isblank (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a control character.
|
||||||
|
inline boolean isControl(int c)
|
||||||
|
{
|
||||||
|
return ( iscntrl (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a digit (0 through 9).
|
||||||
|
inline boolean isDigit(int c)
|
||||||
|
{
|
||||||
|
return ( isdigit (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character except space.
|
||||||
|
inline boolean isGraph(int c)
|
||||||
|
{
|
||||||
|
return ( isgraph (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a lower-case character.
|
||||||
|
inline boolean isLowerCase(int c)
|
||||||
|
{
|
||||||
|
return (islower (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character including space.
|
||||||
|
inline boolean isPrintable(int c)
|
||||||
|
{
|
||||||
|
return ( isprint (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for any printable character which is not a space
|
||||||
|
// or an alphanumeric character.
|
||||||
|
inline boolean isPunct(int c)
|
||||||
|
{
|
||||||
|
return ( ispunct (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for white-space characters. For the avr-libc library,
|
||||||
|
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||||
|
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||||
|
inline boolean isSpace(int c)
|
||||||
|
{
|
||||||
|
return ( isspace (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for an uppercase letter.
|
||||||
|
inline boolean isUpperCase(int c)
|
||||||
|
{
|
||||||
|
return ( isupper (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||||
|
// 8 9 a b c d e f A B C D E F.
|
||||||
|
inline boolean isHexadecimalDigit(int c)
|
||||||
|
{
|
||||||
|
return ( isxdigit (c) == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts c to a 7-bit unsigned char value that fits into the
|
||||||
|
// ASCII character set, by clearing the high-order bits.
|
||||||
|
inline int toAscii(int c)
|
||||||
|
{
|
||||||
|
return toascii (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Warning:
|
||||||
|
// Many people will be unhappy if you use this function.
|
||||||
|
// This function will convert accented letters into random
|
||||||
|
// characters.
|
||||||
|
|
||||||
|
// Converts the letter c to lower case, if possible.
|
||||||
|
inline int toLowerCase(int c)
|
||||||
|
{
|
||||||
|
return tolower (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts the letter c to upper case, if possible.
|
||||||
|
inline int toUpperCase(int c)
|
||||||
|
{
|
||||||
|
return toupper (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1
hardware/digistump/avr/cores/tiny/WConstants.h
Normal file
1
hardware/digistump/avr/cores/tiny/WConstants.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "wiring.h"
|
148
hardware/digistump/avr/cores/tiny/WInterrupts.c
Normal file
148
hardware/digistump/avr/cores/tiny/WInterrupts.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Wiring project - http://wiring.uniandes.edu.co
|
||||||
|
|
||||||
|
Copyright (c) 2004-05 Hernando Barragan
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Modified 24 November 2006 by David A. Mellis
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 09-10-2009 for attiny45 A.Saporetti
|
||||||
|
Modified 20-11-2010 - B.Cook - Correct a minor bug in attachInterrupt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "WConstants.h"
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
volatile static voidFuncPtr intFunc[NUMBER_EXTERNAL_INTERRUPTS];
|
||||||
|
|
||||||
|
#if defined( MCUCR ) && ! defined( EICRA )
|
||||||
|
#define EICRA MCUCR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( GIMSK ) && ! defined( EIMSK )
|
||||||
|
#define EIMSK GIMSK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
|
||||||
|
{
|
||||||
|
if ( interruptNum < NUMBER_EXTERNAL_INTERRUPTS )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If attachInterrupt is called in succession for the same
|
||||||
|
interruptNum but a different userFunc then the following line
|
||||||
|
is not safe. Changing intFunc is not atomic.
|
||||||
|
intFunc[interruptNum] = userFunc;
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
// save interrupt flag
|
||||||
|
uint8_t SaveSREG = SREG;
|
||||||
|
// disable interrupts
|
||||||
|
cli();
|
||||||
|
// access the shared data
|
||||||
|
intFunc[interruptNum] = userFunc;
|
||||||
|
// restore the interrupt flag
|
||||||
|
SREG = SaveSREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the interrupt mode (trigger on low input, any change, rising
|
||||||
|
// edge, or falling edge). The mode constants were chosen to correspond
|
||||||
|
// to the configuration bits in the hardware register, so we simply shift
|
||||||
|
// the mode into place.
|
||||||
|
|
||||||
|
// Enable the interrupt.
|
||||||
|
|
||||||
|
switch ( interruptNum )
|
||||||
|
{
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
case EXTERNAL_INTERRUPT_0:
|
||||||
|
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
|
||||||
|
EIMSK |= (1 << INT0);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2
|
||||||
|
case EXTERNAL_INTERRUPT_1:
|
||||||
|
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
|
||||||
|
EIMSK |= (1 << INT1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS > 2
|
||||||
|
#error Add handlers for the additional interrupts.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void detachInterrupt(uint8_t interruptNum)
|
||||||
|
{
|
||||||
|
if ( interruptNum < NUMBER_EXTERNAL_INTERRUPTS )
|
||||||
|
{
|
||||||
|
// Disable the interrupt. (We can't assume that interruptNum is equal
|
||||||
|
// to the number of the EIMSK bit to clear, as this isn't true on the
|
||||||
|
// ATmega8. There, INT0 is 6 and INT1 is 7.)
|
||||||
|
|
||||||
|
switch (interruptNum)
|
||||||
|
{
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
case EXTERNAL_INTERRUPT_0:
|
||||||
|
EIMSK &= ~(1 << INT0);
|
||||||
|
break;;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2
|
||||||
|
case EXTERNAL_INTERRUPT_1:
|
||||||
|
EIMSK &= ~(1 << INT1);
|
||||||
|
break;;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS > 2
|
||||||
|
#error Add handlers for the additional interrupts.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
intFunc[interruptNum] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
ISR(EXTERNAL_INTERRUPT_0_vect, ISR_NOBLOCK)
|
||||||
|
{
|
||||||
|
if(intFunc[EXTERNAL_INTERRUPT_0])
|
||||||
|
intFunc[EXTERNAL_INTERRUPT_0]();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2
|
||||||
|
ISR(EXTERNAL_INTERRUPT_1_vect, ISR_NOBLOCK)
|
||||||
|
{
|
||||||
|
if(intFunc[EXTERNAL_INTERRUPT_1])
|
||||||
|
intFunc[EXTERNAL_INTERRUPT_1]();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS > 2
|
||||||
|
#error Add handlers for the additional interrupts.
|
||||||
|
#endif
|
60
hardware/digistump/avr/cores/tiny/WMath.cpp
Normal file
60
hardware/digistump/avr/cores/tiny/WMath.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Wiring project - http://wiring.org.co
|
||||||
|
Copyright (c) 2004-06 Hernando Barragan
|
||||||
|
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "stdlib.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void randomSeed(unsigned int seed)
|
||||||
|
{
|
||||||
|
if (seed != 0) {
|
||||||
|
srandom(seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long random(long howbig)
|
||||||
|
{
|
||||||
|
if (howbig == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return random() % howbig;
|
||||||
|
}
|
||||||
|
|
||||||
|
long random(long howsmall, long howbig)
|
||||||
|
{
|
||||||
|
if (howsmall >= howbig) {
|
||||||
|
return howsmall;
|
||||||
|
}
|
||||||
|
long diff = howbig - howsmall;
|
||||||
|
return random(diff) + howsmall;
|
||||||
|
}
|
||||||
|
|
||||||
|
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||||
|
{
|
||||||
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int makeWord(unsigned int w) { return w; }
|
||||||
|
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }
|
83
hardware/digistump/avr/cores/tiny/WProgram.h
Normal file
83
hardware/digistump/avr/cores/tiny/WProgram.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#ifndef WProgram_h
|
||||||
|
#define WProgram_h
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "core_pins.h"
|
||||||
|
#include "wiring.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include "WCharacter.h"
|
||||||
|
#include "WString.h"
|
||||||
|
#include "TinyDebugSerial.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
|
||||||
|
uint16_t makeWord(uint16_t w);
|
||||||
|
uint16_t makeWord(byte h, byte l);
|
||||||
|
|
||||||
|
#define word(...) makeWord(__VA_ARGS__)
|
||||||
|
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
|
|
||||||
|
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
|
||||||
|
void noTone(uint8_t _pin = 255);
|
||||||
|
|
||||||
|
// WMath prototypes
|
||||||
|
long random(long);
|
||||||
|
long random(long, long);
|
||||||
|
void randomSeed(unsigned int);
|
||||||
|
long map(long, long, long, long, long);
|
||||||
|
|
||||||
|
/*
|
||||||
|
fix? On the Mega processors, the analogs are also "extended" digital pins.
|
||||||
|
To (sort of) work the same way with this core, the following constants
|
||||||
|
would have to be valid arguments to digitalRead, digitalWrite, and pinMode
|
||||||
|
("the digitals"). Which means the digitals would have to check for pins
|
||||||
|
over A0 and then subtract A0. The current plan is to wait until someone
|
||||||
|
wants this feature.
|
||||||
|
*/
|
||||||
|
#if CORE_ANALOG_COUNT >= 1
|
||||||
|
const static uint8_t A0 = CORE_ANALOG_FIRST + 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 2
|
||||||
|
const static uint8_t A1 = CORE_ANALOG_FIRST + 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 3
|
||||||
|
const static uint8_t A2 = CORE_ANALOG_FIRST + 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 4
|
||||||
|
const static uint8_t A3 = CORE_ANALOG_FIRST + 3;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 5
|
||||||
|
const static uint8_t A4 = CORE_ANALOG_FIRST + 4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 6
|
||||||
|
const static uint8_t A5 = CORE_ANALOG_FIRST + 5;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 7
|
||||||
|
const static uint8_t A6 = CORE_ANALOG_FIRST + 6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 8
|
||||||
|
const static uint8_t A7 = CORE_ANALOG_FIRST + 7;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_ANALOG_COUNT >= 9
|
||||||
|
#error Update the A* definitions for the selected processor.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
443
hardware/digistump/avr/cores/tiny/WString.cpp
Normal file
443
hardware/digistump/avr/cores/tiny/WString.cpp
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
/*
|
||||||
|
WString.cpp - String library for Wiring & Arduino
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "WProgram.h"
|
||||||
|
#include "WString.h"
|
||||||
|
|
||||||
|
|
||||||
|
String::String( const char *value )
|
||||||
|
{
|
||||||
|
if ( value == NULL )
|
||||||
|
value = "";
|
||||||
|
getBuffer( _length = strlen( value ) );
|
||||||
|
if ( _buffer != NULL )
|
||||||
|
strcpy( _buffer, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String( const String &value )
|
||||||
|
{
|
||||||
|
getBuffer( _length = value._length );
|
||||||
|
if ( _buffer != NULL )
|
||||||
|
strcpy( _buffer, value._buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String( const char value )
|
||||||
|
{
|
||||||
|
_length = 1;
|
||||||
|
getBuffer(1);
|
||||||
|
if ( _buffer != NULL ) {
|
||||||
|
_buffer[0] = value;
|
||||||
|
_buffer[1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String( const unsigned char value )
|
||||||
|
{
|
||||||
|
_length = 1;
|
||||||
|
getBuffer(1);
|
||||||
|
if ( _buffer != NULL) {
|
||||||
|
_buffer[0] = value;
|
||||||
|
_buffer[1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String( const int value, const int base )
|
||||||
|
{
|
||||||
|
char buf[33];
|
||||||
|
itoa((signed long)value, buf, base);
|
||||||
|
getBuffer( _length = strlen(buf) );
|
||||||
|
if ( _buffer != NULL )
|
||||||
|
strcpy( _buffer, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String( const unsigned int value, const int base )
|
||||||
|
{
|
||||||
|
char buf[33];
|
||||||
|
ultoa((unsigned long)value, buf, base);
|
||||||
|
getBuffer( _length = strlen(buf) );
|
||||||
|
if ( _buffer != NULL )
|
||||||
|
strcpy( _buffer, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String( const long value, const int base )
|
||||||
|
{
|
||||||
|
char buf[33];
|
||||||
|
ltoa(value, buf, base);
|
||||||
|
getBuffer( _length = strlen(buf) );
|
||||||
|
if ( _buffer != NULL )
|
||||||
|
strcpy( _buffer, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String( const unsigned long value, const int base )
|
||||||
|
{
|
||||||
|
char buf[33];
|
||||||
|
ultoa(value, buf, 10);
|
||||||
|
getBuffer( _length = strlen(buf) );
|
||||||
|
if ( _buffer != NULL )
|
||||||
|
strcpy( _buffer, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
char String::charAt( unsigned int loc ) const
|
||||||
|
{
|
||||||
|
return operator[]( loc );
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::setCharAt( unsigned int loc, const char aChar )
|
||||||
|
{
|
||||||
|
if(_buffer == NULL) return;
|
||||||
|
if(_length > loc) {
|
||||||
|
_buffer[loc] = aChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::compareTo( const String &s2 ) const
|
||||||
|
{
|
||||||
|
return strcmp( _buffer, s2._buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
const String & String::concat( const String &s2 )
|
||||||
|
{
|
||||||
|
return (*this) += s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String & String::operator=( const String &rhs )
|
||||||
|
{
|
||||||
|
if ( this == &rhs )
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
if ( rhs._length > _length )
|
||||||
|
{
|
||||||
|
free(_buffer);
|
||||||
|
getBuffer( rhs._length );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( _buffer != NULL ) {
|
||||||
|
_length = rhs._length;
|
||||||
|
strcpy( _buffer, rhs._buffer );
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//const String & String::operator+=( const char aChar )
|
||||||
|
//{
|
||||||
|
// if ( _length == _capacity )
|
||||||
|
// doubleBuffer();
|
||||||
|
//
|
||||||
|
// _buffer[ _length++ ] = aChar;
|
||||||
|
// _buffer[ _length ] = '\0';
|
||||||
|
// return *this;
|
||||||
|
//}
|
||||||
|
|
||||||
|
const String & String::operator+=( const String &other )
|
||||||
|
{
|
||||||
|
_length += other._length;
|
||||||
|
if ( _length > _capacity )
|
||||||
|
{
|
||||||
|
char *temp = (char *)realloc(_buffer, _length + 1);
|
||||||
|
if ( temp != NULL ) {
|
||||||
|
_buffer = temp;
|
||||||
|
_capacity = _length;
|
||||||
|
} else {
|
||||||
|
_length -= other._length;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcat( _buffer, other._buffer );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int String::operator==( const String &rhs ) const
|
||||||
|
{
|
||||||
|
return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::operator!=( const String &rhs ) const
|
||||||
|
{
|
||||||
|
return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::operator<( const String &rhs ) const
|
||||||
|
{
|
||||||
|
return strcmp( _buffer, rhs._buffer ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::operator>( const String &rhs ) const
|
||||||
|
{
|
||||||
|
return strcmp( _buffer, rhs._buffer ) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::operator<=( const String &rhs ) const
|
||||||
|
{
|
||||||
|
return strcmp( _buffer, rhs._buffer ) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::operator>=( const String & rhs ) const
|
||||||
|
{
|
||||||
|
return strcmp( _buffer, rhs._buffer ) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char & String::operator[]( unsigned int index )
|
||||||
|
{
|
||||||
|
static char dummy_writable_char;
|
||||||
|
if (index >= _length || !_buffer) {
|
||||||
|
dummy_writable_char = 0;
|
||||||
|
return dummy_writable_char;
|
||||||
|
}
|
||||||
|
return _buffer[ index ];
|
||||||
|
}
|
||||||
|
|
||||||
|
char String::operator[]( unsigned int index ) const
|
||||||
|
{
|
||||||
|
// need to check for valid index, to do later
|
||||||
|
return _buffer[ index ];
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean String::endsWith( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if ( _length < s2._length )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean String::equals( const String &s2 ) const
|
||||||
|
{
|
||||||
|
return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean String::equalsIgnoreCase( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if ( this == &s2 )
|
||||||
|
return true; //1;
|
||||||
|
else if ( _length != s2._length )
|
||||||
|
return false; //0;
|
||||||
|
|
||||||
|
return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::replace( char findChar, char replaceChar )
|
||||||
|
{
|
||||||
|
if ( _buffer == NULL ) return *this;
|
||||||
|
String theReturn = _buffer;
|
||||||
|
char* temp = theReturn._buffer;
|
||||||
|
while( (temp = strchr( temp, findChar )) != 0 )
|
||||||
|
*temp = replaceChar;
|
||||||
|
|
||||||
|
return theReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::replace( const String& match, const String& replace )
|
||||||
|
{
|
||||||
|
if ( _buffer == NULL ) return *this;
|
||||||
|
String temp = _buffer, newString;
|
||||||
|
|
||||||
|
int loc;
|
||||||
|
while ( (loc = temp.indexOf( match )) != -1 )
|
||||||
|
{
|
||||||
|
newString += temp.substring( 0, loc );
|
||||||
|
newString += replace;
|
||||||
|
temp = temp.substring( loc + match._length );
|
||||||
|
}
|
||||||
|
newString += temp;
|
||||||
|
return newString;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf( char temp ) const
|
||||||
|
{
|
||||||
|
return indexOf( temp, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf( char ch, unsigned int fromIndex ) const
|
||||||
|
{
|
||||||
|
if ( fromIndex >= _length )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const char* temp = strchr( &_buffer[fromIndex], ch );
|
||||||
|
if ( temp == NULL )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return temp - _buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf( const String &s2 ) const
|
||||||
|
{
|
||||||
|
return indexOf( s2, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::indexOf( const String &s2, unsigned int fromIndex ) const
|
||||||
|
{
|
||||||
|
if ( fromIndex >= _length )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer );
|
||||||
|
|
||||||
|
if ( theFind == NULL )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return theFind - _buffer; // pointer subtraction
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf( char theChar ) const
|
||||||
|
{
|
||||||
|
return lastIndexOf( theChar, _length - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf( char ch, unsigned int fromIndex ) const
|
||||||
|
{
|
||||||
|
if ( fromIndex >= _length )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char tempchar = _buffer[fromIndex + 1];
|
||||||
|
_buffer[fromIndex + 1] = '\0';
|
||||||
|
char* temp = strrchr( _buffer, ch );
|
||||||
|
_buffer[fromIndex + 1] = tempchar;
|
||||||
|
|
||||||
|
if ( temp == NULL )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return temp - _buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf( const String &s2 ) const
|
||||||
|
{
|
||||||
|
return lastIndexOf( s2, _length - s2._length );
|
||||||
|
}
|
||||||
|
|
||||||
|
int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const
|
||||||
|
{
|
||||||
|
// check for empty strings
|
||||||
|
if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// matching first character
|
||||||
|
char temp = s2[ 0 ];
|
||||||
|
|
||||||
|
for ( int i = fromIndex; i >= 0; i-- )
|
||||||
|
{
|
||||||
|
if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) )
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean String::startsWith( const String &s2 ) const
|
||||||
|
{
|
||||||
|
if ( _length < s2._length )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return startsWith( s2, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean String::startsWith( const String &s2, unsigned int offset ) const
|
||||||
|
{
|
||||||
|
if ( offset > _length - s2._length )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::substring( unsigned int left ) const
|
||||||
|
{
|
||||||
|
return substring( left, _length );
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::substring( unsigned int left, unsigned int right ) const
|
||||||
|
{
|
||||||
|
if ( left > right )
|
||||||
|
{
|
||||||
|
int temp = right;
|
||||||
|
right = left;
|
||||||
|
left = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( right > _length )
|
||||||
|
{
|
||||||
|
right = _length;
|
||||||
|
}
|
||||||
|
|
||||||
|
char temp = _buffer[ right ]; // save the replaced character
|
||||||
|
_buffer[ right ] = '\0';
|
||||||
|
String outPut = ( _buffer + left ); // pointer arithmetic
|
||||||
|
_buffer[ right ] = temp; //restore character
|
||||||
|
return outPut;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::toLowerCase() const
|
||||||
|
{
|
||||||
|
String temp = _buffer;
|
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < _length; i++ )
|
||||||
|
temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] );
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::toUpperCase() const
|
||||||
|
{
|
||||||
|
String temp = _buffer;
|
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < _length; i++ )
|
||||||
|
temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] );
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String String::trim() const
|
||||||
|
{
|
||||||
|
if ( _buffer == NULL ) return *this;
|
||||||
|
String temp = _buffer;
|
||||||
|
unsigned int i,j;
|
||||||
|
|
||||||
|
for ( i = 0; i < _length; i++ )
|
||||||
|
{
|
||||||
|
if ( !isspace(_buffer[i]) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( j = temp._length - 1; j > i; j-- )
|
||||||
|
{
|
||||||
|
if ( !isspace(_buffer[j]) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp.substring( i, j + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::getBytes(unsigned char *buf, unsigned int bufsize)
|
||||||
|
{
|
||||||
|
if (!bufsize || !buf) return;
|
||||||
|
unsigned int len = bufsize - 1;
|
||||||
|
if (len > _length) len = _length;
|
||||||
|
strncpy((char *)buf, _buffer, len);
|
||||||
|
buf[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::toCharArray(char *buf, unsigned int bufsize)
|
||||||
|
{
|
||||||
|
if (!bufsize || !buf) return;
|
||||||
|
unsigned int len = bufsize - 1;
|
||||||
|
if (len > _length) len = _length;
|
||||||
|
strncpy(buf, _buffer, len);
|
||||||
|
buf[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long String::toInt() {
|
||||||
|
return atol(_buffer);
|
||||||
|
}
|
112
hardware/digistump/avr/cores/tiny/WString.h
Normal file
112
hardware/digistump/avr/cores/tiny/WString.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
WString.h - String library for Wiring & Arduino
|
||||||
|
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef String_h
|
||||||
|
#define String_h
|
||||||
|
|
||||||
|
//#include "WProgram.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
String( const char *value = "" );
|
||||||
|
String( const String &value );
|
||||||
|
String( const char );
|
||||||
|
String( const unsigned char );
|
||||||
|
String( const int, const int base=10);
|
||||||
|
String( const unsigned int, const int base=10 );
|
||||||
|
String( const long, const int base=10 );
|
||||||
|
String( const unsigned long, const int base=10 );
|
||||||
|
~String() { free(_buffer); _length = _capacity = 0;} //added _length = _capacity = 0;
|
||||||
|
|
||||||
|
// operators
|
||||||
|
const String & operator = ( const String &rhs );
|
||||||
|
const String & operator +=( const String &rhs );
|
||||||
|
//const String & operator +=( const char );
|
||||||
|
int operator ==( const String &rhs ) const;
|
||||||
|
int operator !=( const String &rhs ) const;
|
||||||
|
int operator < ( const String &rhs ) const;
|
||||||
|
int operator > ( const String &rhs ) const;
|
||||||
|
int operator <=( const String &rhs ) const;
|
||||||
|
int operator >=( const String &rhs ) const;
|
||||||
|
char operator []( unsigned int index ) const;
|
||||||
|
char& operator []( unsigned int index );
|
||||||
|
//operator const char *() const { return _buffer; }
|
||||||
|
|
||||||
|
// general methods
|
||||||
|
char charAt( unsigned int index ) const;
|
||||||
|
int compareTo( const String &anotherString ) const;
|
||||||
|
unsigned char endsWith( const String &suffix ) const;
|
||||||
|
unsigned char equals( const String &anObject ) const;
|
||||||
|
unsigned char equalsIgnoreCase( const String &anotherString ) const;
|
||||||
|
int indexOf( char ch ) const;
|
||||||
|
int indexOf( char ch, unsigned int fromIndex ) const;
|
||||||
|
int indexOf( const String &str ) const;
|
||||||
|
int indexOf( const String &str, unsigned int fromIndex ) const;
|
||||||
|
int lastIndexOf( char ch ) const;
|
||||||
|
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
||||||
|
int lastIndexOf( const String &str ) const;
|
||||||
|
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
||||||
|
const unsigned int length( ) const { return _length; }
|
||||||
|
void setCharAt(unsigned int index, const char ch);
|
||||||
|
unsigned char startsWith( const String &prefix ) const;
|
||||||
|
unsigned char startsWith( const String &prefix, unsigned int toffset ) const;
|
||||||
|
String substring( unsigned int beginIndex ) const;
|
||||||
|
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
||||||
|
String toLowerCase( ) const;
|
||||||
|
String toUpperCase( ) const;
|
||||||
|
String trim( ) const;
|
||||||
|
void getBytes(unsigned char *buf, unsigned int bufsize);
|
||||||
|
void toCharArray(char *buf, unsigned int bufsize);
|
||||||
|
long toInt( );
|
||||||
|
const String& concat( const String &str );
|
||||||
|
String replace( char oldChar, char newChar );
|
||||||
|
String replace( const String& match, const String& replace );
|
||||||
|
friend String operator + ( String lhs, const String &rhs );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char *_buffer; // the actual char array
|
||||||
|
unsigned int _capacity; // the array length minus one (for the '\0')
|
||||||
|
unsigned int _length; // the String length (not counting the '\0')
|
||||||
|
|
||||||
|
void getBuffer(unsigned int maxStrLen);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// allocate buffer space
|
||||||
|
inline void String::getBuffer(unsigned int maxStrLen)
|
||||||
|
{
|
||||||
|
_capacity = maxStrLen;
|
||||||
|
_buffer = (char *) malloc(_capacity + 1);
|
||||||
|
if (_buffer == NULL) _length = _capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline String operator+( String lhs, const String &rhs )
|
||||||
|
{
|
||||||
|
return lhs += rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
515
hardware/digistump/avr/cores/tiny/binary.h
Normal file
515
hardware/digistump/avr/cores/tiny/binary.h
Normal file
@ -0,0 +1,515 @@
|
|||||||
|
#ifndef Binary_h
|
||||||
|
#define Binary_h
|
||||||
|
|
||||||
|
#define B0 0
|
||||||
|
#define B00 0
|
||||||
|
#define B000 0
|
||||||
|
#define B0000 0
|
||||||
|
#define B00000 0
|
||||||
|
#define B000000 0
|
||||||
|
#define B0000000 0
|
||||||
|
#define B00000000 0
|
||||||
|
#define B1 1
|
||||||
|
#define B01 1
|
||||||
|
#define B001 1
|
||||||
|
#define B0001 1
|
||||||
|
#define B00001 1
|
||||||
|
#define B000001 1
|
||||||
|
#define B0000001 1
|
||||||
|
#define B00000001 1
|
||||||
|
#define B10 2
|
||||||
|
#define B010 2
|
||||||
|
#define B0010 2
|
||||||
|
#define B00010 2
|
||||||
|
#define B000010 2
|
||||||
|
#define B0000010 2
|
||||||
|
#define B00000010 2
|
||||||
|
#define B11 3
|
||||||
|
#define B011 3
|
||||||
|
#define B0011 3
|
||||||
|
#define B00011 3
|
||||||
|
#define B000011 3
|
||||||
|
#define B0000011 3
|
||||||
|
#define B00000011 3
|
||||||
|
#define B100 4
|
||||||
|
#define B0100 4
|
||||||
|
#define B00100 4
|
||||||
|
#define B000100 4
|
||||||
|
#define B0000100 4
|
||||||
|
#define B00000100 4
|
||||||
|
#define B101 5
|
||||||
|
#define B0101 5
|
||||||
|
#define B00101 5
|
||||||
|
#define B000101 5
|
||||||
|
#define B0000101 5
|
||||||
|
#define B00000101 5
|
||||||
|
#define B110 6
|
||||||
|
#define B0110 6
|
||||||
|
#define B00110 6
|
||||||
|
#define B000110 6
|
||||||
|
#define B0000110 6
|
||||||
|
#define B00000110 6
|
||||||
|
#define B111 7
|
||||||
|
#define B0111 7
|
||||||
|
#define B00111 7
|
||||||
|
#define B000111 7
|
||||||
|
#define B0000111 7
|
||||||
|
#define B00000111 7
|
||||||
|
#define B1000 8
|
||||||
|
#define B01000 8
|
||||||
|
#define B001000 8
|
||||||
|
#define B0001000 8
|
||||||
|
#define B00001000 8
|
||||||
|
#define B1001 9
|
||||||
|
#define B01001 9
|
||||||
|
#define B001001 9
|
||||||
|
#define B0001001 9
|
||||||
|
#define B00001001 9
|
||||||
|
#define B1010 10
|
||||||
|
#define B01010 10
|
||||||
|
#define B001010 10
|
||||||
|
#define B0001010 10
|
||||||
|
#define B00001010 10
|
||||||
|
#define B1011 11
|
||||||
|
#define B01011 11
|
||||||
|
#define B001011 11
|
||||||
|
#define B0001011 11
|
||||||
|
#define B00001011 11
|
||||||
|
#define B1100 12
|
||||||
|
#define B01100 12
|
||||||
|
#define B001100 12
|
||||||
|
#define B0001100 12
|
||||||
|
#define B00001100 12
|
||||||
|
#define B1101 13
|
||||||
|
#define B01101 13
|
||||||
|
#define B001101 13
|
||||||
|
#define B0001101 13
|
||||||
|
#define B00001101 13
|
||||||
|
#define B1110 14
|
||||||
|
#define B01110 14
|
||||||
|
#define B001110 14
|
||||||
|
#define B0001110 14
|
||||||
|
#define B00001110 14
|
||||||
|
#define B1111 15
|
||||||
|
#define B01111 15
|
||||||
|
#define B001111 15
|
||||||
|
#define B0001111 15
|
||||||
|
#define B00001111 15
|
||||||
|
#define B10000 16
|
||||||
|
#define B010000 16
|
||||||
|
#define B0010000 16
|
||||||
|
#define B00010000 16
|
||||||
|
#define B10001 17
|
||||||
|
#define B010001 17
|
||||||
|
#define B0010001 17
|
||||||
|
#define B00010001 17
|
||||||
|
#define B10010 18
|
||||||
|
#define B010010 18
|
||||||
|
#define B0010010 18
|
||||||
|
#define B00010010 18
|
||||||
|
#define B10011 19
|
||||||
|
#define B010011 19
|
||||||
|
#define B0010011 19
|
||||||
|
#define B00010011 19
|
||||||
|
#define B10100 20
|
||||||
|
#define B010100 20
|
||||||
|
#define B0010100 20
|
||||||
|
#define B00010100 20
|
||||||
|
#define B10101 21
|
||||||
|
#define B010101 21
|
||||||
|
#define B0010101 21
|
||||||
|
#define B00010101 21
|
||||||
|
#define B10110 22
|
||||||
|
#define B010110 22
|
||||||
|
#define B0010110 22
|
||||||
|
#define B00010110 22
|
||||||
|
#define B10111 23
|
||||||
|
#define B010111 23
|
||||||
|
#define B0010111 23
|
||||||
|
#define B00010111 23
|
||||||
|
#define B11000 24
|
||||||
|
#define B011000 24
|
||||||
|
#define B0011000 24
|
||||||
|
#define B00011000 24
|
||||||
|
#define B11001 25
|
||||||
|
#define B011001 25
|
||||||
|
#define B0011001 25
|
||||||
|
#define B00011001 25
|
||||||
|
#define B11010 26
|
||||||
|
#define B011010 26
|
||||||
|
#define B0011010 26
|
||||||
|
#define B00011010 26
|
||||||
|
#define B11011 27
|
||||||
|
#define B011011 27
|
||||||
|
#define B0011011 27
|
||||||
|
#define B00011011 27
|
||||||
|
#define B11100 28
|
||||||
|
#define B011100 28
|
||||||
|
#define B0011100 28
|
||||||
|
#define B00011100 28
|
||||||
|
#define B11101 29
|
||||||
|
#define B011101 29
|
||||||
|
#define B0011101 29
|
||||||
|
#define B00011101 29
|
||||||
|
#define B11110 30
|
||||||
|
#define B011110 30
|
||||||
|
#define B0011110 30
|
||||||
|
#define B00011110 30
|
||||||
|
#define B11111 31
|
||||||
|
#define B011111 31
|
||||||
|
#define B0011111 31
|
||||||
|
#define B00011111 31
|
||||||
|
#define B100000 32
|
||||||
|
#define B0100000 32
|
||||||
|
#define B00100000 32
|
||||||
|
#define B100001 33
|
||||||
|
#define B0100001 33
|
||||||
|
#define B00100001 33
|
||||||
|
#define B100010 34
|
||||||
|
#define B0100010 34
|
||||||
|
#define B00100010 34
|
||||||
|
#define B100011 35
|
||||||
|
#define B0100011 35
|
||||||
|
#define B00100011 35
|
||||||
|
#define B100100 36
|
||||||
|
#define B0100100 36
|
||||||
|
#define B00100100 36
|
||||||
|
#define B100101 37
|
||||||
|
#define B0100101 37
|
||||||
|
#define B00100101 37
|
||||||
|
#define B100110 38
|
||||||
|
#define B0100110 38
|
||||||
|
#define B00100110 38
|
||||||
|
#define B100111 39
|
||||||
|
#define B0100111 39
|
||||||
|
#define B00100111 39
|
||||||
|
#define B101000 40
|
||||||
|
#define B0101000 40
|
||||||
|
#define B00101000 40
|
||||||
|
#define B101001 41
|
||||||
|
#define B0101001 41
|
||||||
|
#define B00101001 41
|
||||||
|
#define B101010 42
|
||||||
|
#define B0101010 42
|
||||||
|
#define B00101010 42
|
||||||
|
#define B101011 43
|
||||||
|
#define B0101011 43
|
||||||
|
#define B00101011 43
|
||||||
|
#define B101100 44
|
||||||
|
#define B0101100 44
|
||||||
|
#define B00101100 44
|
||||||
|
#define B101101 45
|
||||||
|
#define B0101101 45
|
||||||
|
#define B00101101 45
|
||||||
|
#define B101110 46
|
||||||
|
#define B0101110 46
|
||||||
|
#define B00101110 46
|
||||||
|
#define B101111 47
|
||||||
|
#define B0101111 47
|
||||||
|
#define B00101111 47
|
||||||
|
#define B110000 48
|
||||||
|
#define B0110000 48
|
||||||
|
#define B00110000 48
|
||||||
|
#define B110001 49
|
||||||
|
#define B0110001 49
|
||||||
|
#define B00110001 49
|
||||||
|
#define B110010 50
|
||||||
|
#define B0110010 50
|
||||||
|
#define B00110010 50
|
||||||
|
#define B110011 51
|
||||||
|
#define B0110011 51
|
||||||
|
#define B00110011 51
|
||||||
|
#define B110100 52
|
||||||
|
#define B0110100 52
|
||||||
|
#define B00110100 52
|
||||||
|
#define B110101 53
|
||||||
|
#define B0110101 53
|
||||||
|
#define B00110101 53
|
||||||
|
#define B110110 54
|
||||||
|
#define B0110110 54
|
||||||
|
#define B00110110 54
|
||||||
|
#define B110111 55
|
||||||
|
#define B0110111 55
|
||||||
|
#define B00110111 55
|
||||||
|
#define B111000 56
|
||||||
|
#define B0111000 56
|
||||||
|
#define B00111000 56
|
||||||
|
#define B111001 57
|
||||||
|
#define B0111001 57
|
||||||
|
#define B00111001 57
|
||||||
|
#define B111010 58
|
||||||
|
#define B0111010 58
|
||||||
|
#define B00111010 58
|
||||||
|
#define B111011 59
|
||||||
|
#define B0111011 59
|
||||||
|
#define B00111011 59
|
||||||
|
#define B111100 60
|
||||||
|
#define B0111100 60
|
||||||
|
#define B00111100 60
|
||||||
|
#define B111101 61
|
||||||
|
#define B0111101 61
|
||||||
|
#define B00111101 61
|
||||||
|
#define B111110 62
|
||||||
|
#define B0111110 62
|
||||||
|
#define B00111110 62
|
||||||
|
#define B111111 63
|
||||||
|
#define B0111111 63
|
||||||
|
#define B00111111 63
|
||||||
|
#define B1000000 64
|
||||||
|
#define B01000000 64
|
||||||
|
#define B1000001 65
|
||||||
|
#define B01000001 65
|
||||||
|
#define B1000010 66
|
||||||
|
#define B01000010 66
|
||||||
|
#define B1000011 67
|
||||||
|
#define B01000011 67
|
||||||
|
#define B1000100 68
|
||||||
|
#define B01000100 68
|
||||||
|
#define B1000101 69
|
||||||
|
#define B01000101 69
|
||||||
|
#define B1000110 70
|
||||||
|
#define B01000110 70
|
||||||
|
#define B1000111 71
|
||||||
|
#define B01000111 71
|
||||||
|
#define B1001000 72
|
||||||
|
#define B01001000 72
|
||||||
|
#define B1001001 73
|
||||||
|
#define B01001001 73
|
||||||
|
#define B1001010 74
|
||||||
|
#define B01001010 74
|
||||||
|
#define B1001011 75
|
||||||
|
#define B01001011 75
|
||||||
|
#define B1001100 76
|
||||||
|
#define B01001100 76
|
||||||
|
#define B1001101 77
|
||||||
|
#define B01001101 77
|
||||||
|
#define B1001110 78
|
||||||
|
#define B01001110 78
|
||||||
|
#define B1001111 79
|
||||||
|
#define B01001111 79
|
||||||
|
#define B1010000 80
|
||||||
|
#define B01010000 80
|
||||||
|
#define B1010001 81
|
||||||
|
#define B01010001 81
|
||||||
|
#define B1010010 82
|
||||||
|
#define B01010010 82
|
||||||
|
#define B1010011 83
|
||||||
|
#define B01010011 83
|
||||||
|
#define B1010100 84
|
||||||
|
#define B01010100 84
|
||||||
|
#define B1010101 85
|
||||||
|
#define B01010101 85
|
||||||
|
#define B1010110 86
|
||||||
|
#define B01010110 86
|
||||||
|
#define B1010111 87
|
||||||
|
#define B01010111 87
|
||||||
|
#define B1011000 88
|
||||||
|
#define B01011000 88
|
||||||
|
#define B1011001 89
|
||||||
|
#define B01011001 89
|
||||||
|
#define B1011010 90
|
||||||
|
#define B01011010 90
|
||||||
|
#define B1011011 91
|
||||||
|
#define B01011011 91
|
||||||
|
#define B1011100 92
|
||||||
|
#define B01011100 92
|
||||||
|
#define B1011101 93
|
||||||
|
#define B01011101 93
|
||||||
|
#define B1011110 94
|
||||||
|
#define B01011110 94
|
||||||
|
#define B1011111 95
|
||||||
|
#define B01011111 95
|
||||||
|
#define B1100000 96
|
||||||
|
#define B01100000 96
|
||||||
|
#define B1100001 97
|
||||||
|
#define B01100001 97
|
||||||
|
#define B1100010 98
|
||||||
|
#define B01100010 98
|
||||||
|
#define B1100011 99
|
||||||
|
#define B01100011 99
|
||||||
|
#define B1100100 100
|
||||||
|
#define B01100100 100
|
||||||
|
#define B1100101 101
|
||||||
|
#define B01100101 101
|
||||||
|
#define B1100110 102
|
||||||
|
#define B01100110 102
|
||||||
|
#define B1100111 103
|
||||||
|
#define B01100111 103
|
||||||
|
#define B1101000 104
|
||||||
|
#define B01101000 104
|
||||||
|
#define B1101001 105
|
||||||
|
#define B01101001 105
|
||||||
|
#define B1101010 106
|
||||||
|
#define B01101010 106
|
||||||
|
#define B1101011 107
|
||||||
|
#define B01101011 107
|
||||||
|
#define B1101100 108
|
||||||
|
#define B01101100 108
|
||||||
|
#define B1101101 109
|
||||||
|
#define B01101101 109
|
||||||
|
#define B1101110 110
|
||||||
|
#define B01101110 110
|
||||||
|
#define B1101111 111
|
||||||
|
#define B01101111 111
|
||||||
|
#define B1110000 112
|
||||||
|
#define B01110000 112
|
||||||
|
#define B1110001 113
|
||||||
|
#define B01110001 113
|
||||||
|
#define B1110010 114
|
||||||
|
#define B01110010 114
|
||||||
|
#define B1110011 115
|
||||||
|
#define B01110011 115
|
||||||
|
#define B1110100 116
|
||||||
|
#define B01110100 116
|
||||||
|
#define B1110101 117
|
||||||
|
#define B01110101 117
|
||||||
|
#define B1110110 118
|
||||||
|
#define B01110110 118
|
||||||
|
#define B1110111 119
|
||||||
|
#define B01110111 119
|
||||||
|
#define B1111000 120
|
||||||
|
#define B01111000 120
|
||||||
|
#define B1111001 121
|
||||||
|
#define B01111001 121
|
||||||
|
#define B1111010 122
|
||||||
|
#define B01111010 122
|
||||||
|
#define B1111011 123
|
||||||
|
#define B01111011 123
|
||||||
|
#define B1111100 124
|
||||||
|
#define B01111100 124
|
||||||
|
#define B1111101 125
|
||||||
|
#define B01111101 125
|
||||||
|
#define B1111110 126
|
||||||
|
#define B01111110 126
|
||||||
|
#define B1111111 127
|
||||||
|
#define B01111111 127
|
||||||
|
#define B10000000 128
|
||||||
|
#define B10000001 129
|
||||||
|
#define B10000010 130
|
||||||
|
#define B10000011 131
|
||||||
|
#define B10000100 132
|
||||||
|
#define B10000101 133
|
||||||
|
#define B10000110 134
|
||||||
|
#define B10000111 135
|
||||||
|
#define B10001000 136
|
||||||
|
#define B10001001 137
|
||||||
|
#define B10001010 138
|
||||||
|
#define B10001011 139
|
||||||
|
#define B10001100 140
|
||||||
|
#define B10001101 141
|
||||||
|
#define B10001110 142
|
||||||
|
#define B10001111 143
|
||||||
|
#define B10010000 144
|
||||||
|
#define B10010001 145
|
||||||
|
#define B10010010 146
|
||||||
|
#define B10010011 147
|
||||||
|
#define B10010100 148
|
||||||
|
#define B10010101 149
|
||||||
|
#define B10010110 150
|
||||||
|
#define B10010111 151
|
||||||
|
#define B10011000 152
|
||||||
|
#define B10011001 153
|
||||||
|
#define B10011010 154
|
||||||
|
#define B10011011 155
|
||||||
|
#define B10011100 156
|
||||||
|
#define B10011101 157
|
||||||
|
#define B10011110 158
|
||||||
|
#define B10011111 159
|
||||||
|
#define B10100000 160
|
||||||
|
#define B10100001 161
|
||||||
|
#define B10100010 162
|
||||||
|
#define B10100011 163
|
||||||
|
#define B10100100 164
|
||||||
|
#define B10100101 165
|
||||||
|
#define B10100110 166
|
||||||
|
#define B10100111 167
|
||||||
|
#define B10101000 168
|
||||||
|
#define B10101001 169
|
||||||
|
#define B10101010 170
|
||||||
|
#define B10101011 171
|
||||||
|
#define B10101100 172
|
||||||
|
#define B10101101 173
|
||||||
|
#define B10101110 174
|
||||||
|
#define B10101111 175
|
||||||
|
#define B10110000 176
|
||||||
|
#define B10110001 177
|
||||||
|
#define B10110010 178
|
||||||
|
#define B10110011 179
|
||||||
|
#define B10110100 180
|
||||||
|
#define B10110101 181
|
||||||
|
#define B10110110 182
|
||||||
|
#define B10110111 183
|
||||||
|
#define B10111000 184
|
||||||
|
#define B10111001 185
|
||||||
|
#define B10111010 186
|
||||||
|
#define B10111011 187
|
||||||
|
#define B10111100 188
|
||||||
|
#define B10111101 189
|
||||||
|
#define B10111110 190
|
||||||
|
#define B10111111 191
|
||||||
|
#define B11000000 192
|
||||||
|
#define B11000001 193
|
||||||
|
#define B11000010 194
|
||||||
|
#define B11000011 195
|
||||||
|
#define B11000100 196
|
||||||
|
#define B11000101 197
|
||||||
|
#define B11000110 198
|
||||||
|
#define B11000111 199
|
||||||
|
#define B11001000 200
|
||||||
|
#define B11001001 201
|
||||||
|
#define B11001010 202
|
||||||
|
#define B11001011 203
|
||||||
|
#define B11001100 204
|
||||||
|
#define B11001101 205
|
||||||
|
#define B11001110 206
|
||||||
|
#define B11001111 207
|
||||||
|
#define B11010000 208
|
||||||
|
#define B11010001 209
|
||||||
|
#define B11010010 210
|
||||||
|
#define B11010011 211
|
||||||
|
#define B11010100 212
|
||||||
|
#define B11010101 213
|
||||||
|
#define B11010110 214
|
||||||
|
#define B11010111 215
|
||||||
|
#define B11011000 216
|
||||||
|
#define B11011001 217
|
||||||
|
#define B11011010 218
|
||||||
|
#define B11011011 219
|
||||||
|
#define B11011100 220
|
||||||
|
#define B11011101 221
|
||||||
|
#define B11011110 222
|
||||||
|
#define B11011111 223
|
||||||
|
#define B11100000 224
|
||||||
|
#define B11100001 225
|
||||||
|
#define B11100010 226
|
||||||
|
#define B11100011 227
|
||||||
|
#define B11100100 228
|
||||||
|
#define B11100101 229
|
||||||
|
#define B11100110 230
|
||||||
|
#define B11100111 231
|
||||||
|
#define B11101000 232
|
||||||
|
#define B11101001 233
|
||||||
|
#define B11101010 234
|
||||||
|
#define B11101011 235
|
||||||
|
#define B11101100 236
|
||||||
|
#define B11101101 237
|
||||||
|
#define B11101110 238
|
||||||
|
#define B11101111 239
|
||||||
|
#define B11110000 240
|
||||||
|
#define B11110001 241
|
||||||
|
#define B11110010 242
|
||||||
|
#define B11110011 243
|
||||||
|
#define B11110100 244
|
||||||
|
#define B11110101 245
|
||||||
|
#define B11110110 246
|
||||||
|
#define B11110111 247
|
||||||
|
#define B11111000 248
|
||||||
|
#define B11111001 249
|
||||||
|
#define B11111010 250
|
||||||
|
#define B11111011 251
|
||||||
|
#define B11111100 252
|
||||||
|
#define B11111101 253
|
||||||
|
#define B11111110 254
|
||||||
|
#define B11111111 255
|
||||||
|
|
||||||
|
#endif
|
320
hardware/digistump/avr/cores/tiny/core_adc.h
Normal file
320
hardware/digistump/avr/cores/tiny/core_adc.h
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
core_adc.h - Veneer for the analog-to-digital converter.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef core_adc_h
|
||||||
|
#define core_adc_h
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <binary.h>
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "core_macros.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Some common things
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX4__ ) || defined( __AVR_ATtinyX5__ )
|
||||||
|
|
||||||
|
/*
|
||||||
|
From the '84 and '85 datasheets... By default, the successive approximation
|
||||||
|
circuitry requires an input clock frequency between 50 kHz and 200 kHz to
|
||||||
|
get maximum resolution.
|
||||||
|
*/
|
||||||
|
#if F_CPU == 16000000
|
||||||
|
// 16 MHz / 128 = 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER ADC_Prescaler_Value_128
|
||||||
|
#elif F_CPU == 16500000
|
||||||
|
// 8 MHz / 64 = 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER ADC_Prescaler_Value_128
|
||||||
|
#elif F_CPU == 8000000
|
||||||
|
// 8 MHz / 64 = 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER ADC_Prescaler_Value_64
|
||||||
|
#elif F_CPU == 1000000
|
||||||
|
// 1 MHz / 8 = 125 KHz
|
||||||
|
#define ADC_ARDUINO_PRESCALER ADC_Prescaler_Value_8
|
||||||
|
#else
|
||||||
|
#error Add an entry for the selected processor speed.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ADC_Prescaler_Value_2 = B001,
|
||||||
|
ADC_Prescaler_Value_4 = B010,
|
||||||
|
ADC_Prescaler_Value_8 = B011,
|
||||||
|
ADC_Prescaler_Value_16 = B100,
|
||||||
|
ADC_Prescaler_Value_32 = B101,
|
||||||
|
ADC_Prescaler_Value_64 = B110,
|
||||||
|
ADC_Prescaler_Value_128 = B111,
|
||||||
|
ADC_Prescaler_Index_1 = B001,
|
||||||
|
ADC_Prescaler_Index_2 = B010,
|
||||||
|
ADC_Prescaler_Index_3 = B011,
|
||||||
|
ADC_Prescaler_Index_4 = B100,
|
||||||
|
ADC_Prescaler_Index_5 = B101,
|
||||||
|
ADC_Prescaler_Index_6 = B110,
|
||||||
|
ADC_Prescaler_Index_7 = B111
|
||||||
|
}
|
||||||
|
adc_ps_t;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_PrescalerSelect( adc_ps_t ps )
|
||||||
|
{
|
||||||
|
ADCSRA = (ADCSRA & ~MASK3(ADPS2,ADPS1,ADPS0)) | (ps << ADPS0);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_Enable( void )
|
||||||
|
{
|
||||||
|
ADCSRA |= MASK1( ADEN );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Veneer for the ATtiny84 ADC
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX4__ )
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ADC_Reference_VCC = B00,
|
||||||
|
ADC_Reference_External = B01,
|
||||||
|
ADC_Reference_Internal_1p1 = B10,
|
||||||
|
ADC_Reference_Reserved_1 = B11
|
||||||
|
}
|
||||||
|
adc_vr_t;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_SetVoltageReference( adc_vr_t vr )
|
||||||
|
{
|
||||||
|
ADMUX = (ADMUX & ~MASK2(REFS1,REFS0)) | (((vr & B11) >> 0) << REFS0);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ADC_Input_ADC0 = B000000,
|
||||||
|
ADC_Input_ADC1 = B000001,
|
||||||
|
ADC_Input_ADC2 = B000010,
|
||||||
|
ADC_Input_ADC3 = B000011,
|
||||||
|
ADC_Input_ADC4 = B000100,
|
||||||
|
ADC_Input_ADC5 = B000101,
|
||||||
|
ADC_Input_ADC6 = B000110,
|
||||||
|
ADC_Input_ADC7 = B000111,
|
||||||
|
|
||||||
|
ADC_Input_GND = B100000, // 0V (AGND)
|
||||||
|
ADC_Input_1p1 = B100001, // 1.1V (I Ref)
|
||||||
|
ADC_Input_ADC8 = B100010, // For temperature sensor.
|
||||||
|
|
||||||
|
ADC_Input_Pos0_Neg0_20x = B100011, // For offset calibration, only.
|
||||||
|
ADC_Input_Pos0_Neg1_1x = B001000,
|
||||||
|
ADC_Input_Pos0_Neg1_20x = B001001,
|
||||||
|
ADC_Input_Pos0_Neg3_1x = B001010,
|
||||||
|
ADC_Input_Pos0_Neg3_20x = B001011,
|
||||||
|
ADC_Input_Pos1_Neg0_1x = B101000,
|
||||||
|
ADC_Input_Pos1_Neg0_20x = B101001,
|
||||||
|
ADC_Input_Pos1_Neg2_1x = B001100,
|
||||||
|
ADC_Input_Pos1_Neg2_20x = B001101,
|
||||||
|
ADC_Input_Pos1_Neg3_1x = B001110,
|
||||||
|
ADC_Input_Pos1_Neg3_20x = B001111,
|
||||||
|
ADC_Input_Pos2_Neg1_1x = B101100,
|
||||||
|
ADC_Input_Pos2_Neg1_20x = B101101,
|
||||||
|
ADC_Input_Pos2_Neg3_1x = B010000,
|
||||||
|
ADC_Input_Pos2_Neg3_20x = B010001,
|
||||||
|
ADC_Input_Pos3_Neg0_1x = B101010,
|
||||||
|
ADC_Input_Pos3_Neg0_20x = B101011,
|
||||||
|
ADC_Input_Pos3_Neg1_1x = B101110,
|
||||||
|
ADC_Input_Pos3_Neg1_20x = B101111,
|
||||||
|
ADC_Input_Pos3_Neg2_1x = B110000,
|
||||||
|
ADC_Input_Pos3_Neg2_20x = B110001,
|
||||||
|
ADC_Input_Pos3_Neg3_1x = B100100, // For offset calibration, only.
|
||||||
|
ADC_Input_Pos3_Neg3_20x = B100101, // For offset calibration, only.
|
||||||
|
ADC_Input_Pos3_Neg4_1x = B010010,
|
||||||
|
ADC_Input_Pos3_Neg4_20x = B010011,
|
||||||
|
ADC_Input_Pos3_Neg5_1x = B010100,
|
||||||
|
ADC_Input_Pos3_Neg5_20x = B010101,
|
||||||
|
ADC_Input_Pos3_Neg6_1x = B010110,
|
||||||
|
ADC_Input_Pos3_Neg6_20x = B010111,
|
||||||
|
ADC_Input_Pos3_Neg7_1x = B011000,
|
||||||
|
ADC_Input_Pos3_Neg7_20x = B011001,
|
||||||
|
ADC_Input_Pos4_Neg3_1x = B110010,
|
||||||
|
ADC_Input_Pos4_Neg3_20x = B110011,
|
||||||
|
ADC_Input_Pos4_Neg5_1x = B011010,
|
||||||
|
ADC_Input_Pos4_Neg5_20x = B011011,
|
||||||
|
ADC_Input_Pos5_Neg3_1x = B110100,
|
||||||
|
ADC_Input_Pos5_Neg3_20x = B110101,
|
||||||
|
ADC_Input_Pos5_Neg4_1x = B111010,
|
||||||
|
ADC_Input_Pos5_Neg4_20x = B111011,
|
||||||
|
ADC_Input_Pos5_Neg6_1x = B011100,
|
||||||
|
ADC_Input_Pos5_Neg6_20x = B011101,
|
||||||
|
ADC_Input_Pos6_Neg3_1x = B110110,
|
||||||
|
ADC_Input_Pos6_Neg3_20x = B110111,
|
||||||
|
ADC_Input_Pos6_Neg5_1x = B111100,
|
||||||
|
ADC_Input_Pos6_Neg5_20x = B111101,
|
||||||
|
ADC_Input_Pos6_Neg7_1x = B011110,
|
||||||
|
ADC_Input_Pos6_Neg7_20x = B011111,
|
||||||
|
ADC_Input_Pos7_Neg3_1x = B111000,
|
||||||
|
ADC_Input_Pos7_Neg3_20x = B111001,
|
||||||
|
ADC_Input_Pos7_Neg6_1x = B111110,
|
||||||
|
ADC_Input_Pos7_Neg6_20x = B111111,
|
||||||
|
ADC_Input_Pos7_Neg7_1x = B100110, // For offset calibration, only.
|
||||||
|
ADC_Input_Pos7_Neg7_20x = B100111 // For offset calibration, only.
|
||||||
|
}
|
||||||
|
adc_ic_t;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_SetInputChannel( adc_ic_t ic )
|
||||||
|
{
|
||||||
|
ADMUX = (ADMUX & ~MASK6(MUX5,MUX4,MUX3,MUX2,MUX1,MUX0)) | (ic << MUX0);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_StartConversion( void )
|
||||||
|
{
|
||||||
|
ADCSRA |= MASK1( ADSC );
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint8_t ADC_ConversionInProgress( void )
|
||||||
|
{
|
||||||
|
return( (ADCSRA & (1<<ADSC)) != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint16_t ADC_GetDataRegister( void )
|
||||||
|
{
|
||||||
|
return( ADC );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Veneer for the ATtiny85 ADC
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX5__ )
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ADC_Reference_VCC = B000,
|
||||||
|
ADC_Reference_External = B001,
|
||||||
|
ADC_Reference_Internal_1p1 = B010,
|
||||||
|
ADC_Reference_Reserved_1 = B011,
|
||||||
|
ADC_Reference_Internal_2p56 = B110,
|
||||||
|
ADC_Reference_Internal_2p56_Bypass_Capacitor = B111
|
||||||
|
}
|
||||||
|
adc_vr_t;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_SetVoltageReference( adc_vr_t vr )
|
||||||
|
{
|
||||||
|
ADMUX = (ADMUX & ~MASK3(REFS1,REFS0,REFS2))
|
||||||
|
| (((vr & B011) >> 0) << REFS0)
|
||||||
|
| (((vr & B100) >> 2) << REFS2);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ADC_Input_ADC0 = B0000,
|
||||||
|
ADC_Input_ADC1 = B0001,
|
||||||
|
ADC_Input_ADC2 = B0010,
|
||||||
|
ADC_Input_ADC3 = B0011,
|
||||||
|
|
||||||
|
ADC_Input_Pos2_Neg2_1x = B0100, // For offset calibration, only.
|
||||||
|
ADC_Input_Pos2_Neg2_20x = B0101, // For offset calibration, only.
|
||||||
|
ADC_Input_Pos2_Neg3_1x = B0110,
|
||||||
|
ADC_Input_Pos2_Neg3_20x = B0111,
|
||||||
|
ADC_Input_Pos0_Neg0_1x = B1000,
|
||||||
|
ADC_Input_Pos0_Neg0_20x = B1001,
|
||||||
|
ADC_Input_Pos0_Neg1_1x = B1010,
|
||||||
|
ADC_Input_Pos0_Neg1_20x = B1011,
|
||||||
|
|
||||||
|
ADC_Input_VBG = B1100,
|
||||||
|
ADC_Input_GND = B1101,
|
||||||
|
ADC_Input_NA = B1110,
|
||||||
|
ADC_Input_ADC4 = B1111 // For temperature sensor.
|
||||||
|
}
|
||||||
|
adc_ic_t;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_SetInputChannel( adc_ic_t ic )
|
||||||
|
{
|
||||||
|
ADMUX = (ADMUX & ~MASK4(MUX3,MUX2,MUX1,MUX0)) | (ic << MUX0);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_StartConversion( void )
|
||||||
|
{
|
||||||
|
ADCSRA |= MASK1( ADSC );
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint8_t ADC_ConversionInProgress( void )
|
||||||
|
{
|
||||||
|
return( (ADCSRA & (1<<ADSC)) != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint16_t ADC_GetDataRegister( void )
|
||||||
|
{
|
||||||
|
return( ADC );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Veneer for the (non-existant) ATtinyX313 ADC
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX313__ )
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ADC_No_Reference = 0
|
||||||
|
}
|
||||||
|
adc_vr_t;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_SetVoltageReference( adc_vr_t vr )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ADC_No_Input = 0
|
||||||
|
}
|
||||||
|
adc_ic_t;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_SetInputChannel( adc_ic_t ic )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline void ADC_StartConversion( void )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint8_t ADC_ConversionInProgress( void )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline uint16_t ADC_GetDataRegister( void )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
174
hardware/digistump/avr/cores/tiny/core_build_options.h
Normal file
174
hardware/digistump/avr/cores/tiny/core_build_options.h
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
core_build_options.h - Various options for mapping functionality to hardware.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef core_build_options_h
|
||||||
|
#define core_build_options_h
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Low power / smaller code options
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#define INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER 1
|
||||||
|
#define INITIALIZE_SECONDARY_TIMERS 1
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Build options for the ATtinyX313 processor
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtiny2313__ ) || defined( __AVR_ATtiny4313__ )
|
||||||
|
#define __AVR_ATtinyX313__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX313__ )
|
||||||
|
|
||||||
|
/*
|
||||||
|
The old standby ... millis on Timer 0.
|
||||||
|
*/
|
||||||
|
#define TIMER_TO_USE_FOR_MILLIS 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tone goes on whichever timer was not used for millis.
|
||||||
|
*/
|
||||||
|
#if TIMER_TO_USE_FOR_MILLIS == 1
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 0
|
||||||
|
#else
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_ADC 0
|
||||||
|
|
||||||
|
#define DEFAULT_TO_TINY_DEBUG_SERIAL 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Build options for the ATtiny84 processor
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtiny24__ ) || defined( __AVR_ATtiny44__ ) || defined( __AVR_ATtiny84__ )
|
||||||
|
#define __AVR_ATtinyX4__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX4__ )
|
||||||
|
|
||||||
|
/*
|
||||||
|
The old standby ... millis on Timer 0.
|
||||||
|
*/
|
||||||
|
#define TIMER_TO_USE_FOR_MILLIS 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tone goes on whichever timer was not used for millis.
|
||||||
|
*/
|
||||||
|
#if TIMER_TO_USE_FOR_MILLIS == 1
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 0
|
||||||
|
#else
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_ADC 1
|
||||||
|
|
||||||
|
#define DEFAULT_TO_TINY_DEBUG_SERIAL 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Build options for the ATtiny85 processor
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ )
|
||||||
|
#define __AVR_ATtinyX5__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX5__ )
|
||||||
|
|
||||||
|
/*
|
||||||
|
For various reasons, Timer 1 is a better choice for the millis timer on the
|
||||||
|
'85 processor.
|
||||||
|
*/
|
||||||
|
#define TIMER_TO_USE_FOR_MILLIS 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the following is true (non-zero) there will be two phase-correct PWM
|
||||||
|
pins and one fast PWM pin. If false there will be one phase-correct PWM
|
||||||
|
pin and two fast PWM pins.
|
||||||
|
*/
|
||||||
|
#define FAVOR_PHASE_CORRECT_PWM 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tone goes on whichever timer was not used for millis.
|
||||||
|
*/
|
||||||
|
#if TIMER_TO_USE_FOR_MILLIS == 1
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 0
|
||||||
|
#else
|
||||||
|
#define TIMER_TO_USE_FOR_TONE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HAVE_ADC 1
|
||||||
|
|
||||||
|
#define DEFAULT_TO_TINY_DEBUG_SERIAL 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
There doesn't seem to be many people using a bootloader so we'll assume
|
||||||
|
there isn't one. If the following is true (non-zero), the timers are
|
||||||
|
reinitialized to their power-up state in init just in case the bootloader
|
||||||
|
left them in a bad way.
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#define HAVE_BOOTLOADER 0
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Allow the ADC to be optional for low-power applications
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if ! defined( HAVE_ADC )
|
||||||
|
#define HAVE_ADC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ! HAVE_ADC
|
||||||
|
#undef INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
|
||||||
|
#define INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER 0
|
||||||
|
#else
|
||||||
|
#if ! defined( INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER )
|
||||||
|
#define INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Allow the "secondary timers" to be optional for low-power applications
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if ! defined( INITIALIZE_SECONDARY_TIMERS )
|
||||||
|
#define INITIALIZE_SECONDARY_TIMERS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
42
hardware/digistump/avr/cores/tiny/core_macros.h
Normal file
42
hardware/digistump/avr/cores/tiny/core_macros.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
core_macros.h - Simple but handy macros.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef core_macros_h
|
||||||
|
#define core_macros_h
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Bitmask macros
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#define MASK1(b1) ( (1<<b1) )
|
||||||
|
#define MASK2(b1,b2) ( (1<<b1) | (1<<b2) )
|
||||||
|
#define MASK3(b1,b2,b3) ( (1<<b1) | (1<<b2) | (1<<b3) )
|
||||||
|
#define MASK4(b1,b2,b3,b4) ( (1<<b1) | (1<<b2) | (1<<b3) | (1<<b4) )
|
||||||
|
#define MASK5(b1,b2,b3,b4,b5) ( (1<<b1) | (1<<b2) | (1<<b3) | (1<<b4) | (1<<b5) )
|
||||||
|
#define MASK6(b1,b2,b3,b4,b5,b6) ( (1<<b1) | (1<<b2) | (1<<b3) | (1<<b4) | (1<<b5) | (1<<b6) )
|
||||||
|
#define MASK7(b1,b2,b3,b4,b5,b6,b7) ( (1<<b1) | (1<<b2) | (1<<b3) | (1<<b4) | (1<<b5) | (1<<b6) | (1<<b7) )
|
||||||
|
#define MASK8(b1,b2,b3,b4,b5,b6,b7,b8) ( (1<<b1) | (1<<b2) | (1<<b3) | (1<<b4) | (1<<b5) | (1<<b6) | (1<<b7) | (1<<b8) )
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
204
hardware/digistump/avr/cores/tiny/core_pins.h
Normal file
204
hardware/digistump/avr/cores/tiny/core_pins.h
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
/*==============================================================================
|
||||||
|
|
||||||
|
core_pins.h - Pin definitions.
|
||||||
|
|
||||||
|
Copyright 2010 Rowdy Dog Software.
|
||||||
|
|
||||||
|
This file is part of Arduino-Tiny.
|
||||||
|
|
||||||
|
Arduino-Tiny is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Arduino-Tiny is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with Arduino-Tiny. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef core_pins_h
|
||||||
|
#define core_pins_h
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Pin definitions for the ATtinyX313
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX313__ )
|
||||||
|
|
||||||
|
#define PIN_D0 ( 0)
|
||||||
|
#define PIN_D1 ( 1)
|
||||||
|
#define PIN_A1 ( 2)
|
||||||
|
#define PIN_A0 ( 3)
|
||||||
|
#define PIN_D2 ( 4)
|
||||||
|
#define PIN_D3 ( 5)
|
||||||
|
#define PIN_D4 ( 6)
|
||||||
|
#define PIN_D5 ( 7)
|
||||||
|
#define PIN_D6 ( 8)
|
||||||
|
#define PIN_B0 ( 9)
|
||||||
|
#define PIN_B1 (10)
|
||||||
|
#define PIN_B2 (11)
|
||||||
|
#define PIN_B3 (12)
|
||||||
|
#define PIN_B4 (13)
|
||||||
|
#define PIN_B5 (14)
|
||||||
|
#define PIN_B6 (15)
|
||||||
|
#define PIN_B7 (16)
|
||||||
|
#define PIN_A2 (17) /* RESET */
|
||||||
|
|
||||||
|
#define CORE_DIGITAL_FIRST (0)
|
||||||
|
#define CORE_DIGITAL_LAST (17)
|
||||||
|
#define CORE_DIGITAL_COUNT (CORE_DIGITAL_LAST-CORE_DIGITAL_FIRST+1)
|
||||||
|
#define CORE_RESET_INCLUDED (1)
|
||||||
|
|
||||||
|
#define CORE_ANALOG_COUNT (0)
|
||||||
|
|
||||||
|
#define CORE_INT0_PIN PIN_D2
|
||||||
|
#define CORE_INT1_PIN PIN_D3
|
||||||
|
|
||||||
|
#define CORE_OC0A_PIN PIN_B2
|
||||||
|
#define CORE_OC0B_PIN PIN_D5
|
||||||
|
#define CORE_OC1A_PIN PIN_B3
|
||||||
|
#define CORE_OC1B_PIN PIN_B4
|
||||||
|
|
||||||
|
#define CORE_PWM0_PIN CORE_OC0A_PIN
|
||||||
|
#define CORE_PWM0_TIMER 0
|
||||||
|
#define CORE_PWM0_CHANNEL A
|
||||||
|
|
||||||
|
#define CORE_PWM1_PIN CORE_OC0B_PIN
|
||||||
|
#define CORE_PWM1_TIMER 0
|
||||||
|
#define CORE_PWM1_CHANNEL B
|
||||||
|
|
||||||
|
#define CORE_PWM2_PIN CORE_OC1A_PIN
|
||||||
|
#define CORE_PWM2_TIMER 1
|
||||||
|
#define CORE_PWM2_CHANNEL A
|
||||||
|
|
||||||
|
#define CORE_PWM3_PIN CORE_OC1B_PIN
|
||||||
|
#define CORE_PWM3_TIMER 1
|
||||||
|
#define CORE_PWM3_CHANNEL B
|
||||||
|
|
||||||
|
#define CORE_PWM_COUNT (4)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Pin definitions for the ATtiny84
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX4__ )
|
||||||
|
|
||||||
|
#define PIN_A0 (10)
|
||||||
|
#define PIN_A1 ( 9)
|
||||||
|
#define PIN_A2 ( 8)
|
||||||
|
#define PIN_A3 ( 7)
|
||||||
|
#define PIN_A4 ( 6)
|
||||||
|
#define PIN_A5 ( 5)
|
||||||
|
#define PIN_A6 ( 4)
|
||||||
|
#define PIN_A7 ( 3)
|
||||||
|
#define PIN_B0 ( 0)
|
||||||
|
#define PIN_B1 ( 1)
|
||||||
|
#define PIN_B2 ( 2)
|
||||||
|
#define PIN_B3 (11) /* RESET */
|
||||||
|
|
||||||
|
#define CORE_DIGITAL_FIRST (0)
|
||||||
|
#define CORE_DIGITAL_LAST (11)
|
||||||
|
#define CORE_DIGITAL_COUNT (CORE_DIGITAL_LAST-CORE_DIGITAL_FIRST+1)
|
||||||
|
#define CORE_RESET_INCLUDED (1)
|
||||||
|
|
||||||
|
#define CORE_ANALOG_FIRST (CORE_DIGITAL_LAST+1)
|
||||||
|
#define CORE_ANALOG_COUNT (8)
|
||||||
|
#define CORE_ANALOG_LAST (CORE_ANALOG_FIRST+CORE_ANALOG_COUNT-1)
|
||||||
|
|
||||||
|
#define CORE_INT0_PIN PIN_B2
|
||||||
|
|
||||||
|
#define CORE_OC0A_PIN PIN_B2
|
||||||
|
#define CORE_OC0B_PIN PIN_A7
|
||||||
|
#define CORE_OC1A_PIN PIN_A6
|
||||||
|
#define CORE_OC1B_PIN PIN_A5
|
||||||
|
|
||||||
|
#define CORE_PWM0_PIN CORE_OC0A_PIN
|
||||||
|
#define CORE_PWM0_TIMER 0
|
||||||
|
#define CORE_PWM0_CHANNEL A
|
||||||
|
|
||||||
|
#define CORE_PWM1_PIN CORE_OC0B_PIN
|
||||||
|
#define CORE_PWM1_TIMER 0
|
||||||
|
#define CORE_PWM1_CHANNEL B
|
||||||
|
|
||||||
|
#define CORE_PWM2_PIN CORE_OC1A_PIN
|
||||||
|
#define CORE_PWM2_TIMER 1
|
||||||
|
#define CORE_PWM2_CHANNEL A
|
||||||
|
|
||||||
|
#define CORE_PWM3_PIN CORE_OC1B_PIN
|
||||||
|
#define CORE_PWM3_TIMER 1
|
||||||
|
#define CORE_PWM3_CHANNEL B
|
||||||
|
|
||||||
|
#define CORE_PWM_COUNT (4)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Pin definitions for the ATtiny85
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX5__ )
|
||||||
|
|
||||||
|
#define PIN_B0 ( 0)
|
||||||
|
#define PIN_B1 ( 1)
|
||||||
|
#define PIN_B2 ( 2)
|
||||||
|
#define PIN_B3 ( 3)
|
||||||
|
#define PIN_B4 ( 4)
|
||||||
|
#define PIN_B5 ( 5) /* RESET */
|
||||||
|
|
||||||
|
#define CORE_DIGITAL_FIRST (0)
|
||||||
|
#define CORE_DIGITAL_LAST (5)
|
||||||
|
#define CORE_DIGITAL_COUNT (CORE_DIGITAL_LAST-CORE_DIGITAL_FIRST+1)
|
||||||
|
#define CORE_RESET_INCLUDED (1)
|
||||||
|
|
||||||
|
#define CORE_ANALOG_FIRST (CORE_DIGITAL_LAST+1)
|
||||||
|
#define CORE_ANALOG_COUNT (4)
|
||||||
|
#define CORE_ANALOG_LAST (CORE_ANALOG_FIRST+CORE_ANALOG_COUNT-1)
|
||||||
|
|
||||||
|
#define CORE_INT0_PIN PIN_B2
|
||||||
|
|
||||||
|
#define CORE_OC0A_PIN PIN_B0
|
||||||
|
#define CORE_OC0B_PIN PIN_B1
|
||||||
|
#define CORE_OC1A_PIN PIN_B1
|
||||||
|
#define CORE_OC1B_PIN PIN_B4
|
||||||
|
|
||||||
|
/* Note: By default, CORE_OC1A_PIN is not used for PWM. It overlaps with
|
||||||
|
CORE_OC0B_PIN. CORE_OC0B_PIN was used because it supports phase-correct PWM.
|
||||||
|
There is a build option in "core_build_options.h" to determine which channel
|
||||||
|
to use */
|
||||||
|
|
||||||
|
#define CORE_PWM0_PIN CORE_OC0A_PIN
|
||||||
|
#define CORE_PWM0_TIMER 0
|
||||||
|
#define CORE_PWM0_CHANNEL A
|
||||||
|
|
||||||
|
#if FAVOR_PHASE_CORRECT_PWM
|
||||||
|
#define CORE_PWM1_PIN CORE_OC0B_PIN
|
||||||
|
#define CORE_PWM1_TIMER 0
|
||||||
|
#define CORE_PWM1_CHANNEL B
|
||||||
|
#else
|
||||||
|
#define CORE_PWM1_PIN CORE_OC1A_PIN
|
||||||
|
#define CORE_PWM1_TIMER 1
|
||||||
|
#define CORE_PWM1_CHANNEL A
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CORE_PWM2_PIN CORE_OC1B_PIN
|
||||||
|
#define CORE_PWM2_TIMER 1
|
||||||
|
#define CORE_PWM2_CHANNEL B
|
||||||
|
|
||||||
|
#define CORE_PWM_COUNT (3)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
1075
hardware/digistump/avr/cores/tiny/core_timers.h
Normal file
1075
hardware/digistump/avr/cores/tiny/core_timers.h
Normal file
File diff suppressed because it is too large
Load Diff
14
hardware/digistump/avr/cores/tiny/main.cpp
Normal file
14
hardware/digistump/avr/cores/tiny/main.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <WProgram.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
loop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
18
hardware/digistump/avr/cores/tiny/new.cpp
Normal file
18
hardware/digistump/avr/cores/tiny/new.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <new.h>
|
||||||
|
|
||||||
|
void * operator new(size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void * ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
|
||||||
|
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
|
||||||
|
void __cxa_guard_abort (__guard *) {};
|
||||||
|
|
||||||
|
void __cxa_pure_virtual(void) {};
|
||||||
|
|
22
hardware/digistump/avr/cores/tiny/new.h
Normal file
22
hardware/digistump/avr/cores/tiny/new.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* Header to define new/delete operators as they aren't provided by avr-gcc by default
|
||||||
|
Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NEW_H
|
||||||
|
#define NEW_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void * operator new(size_t size);
|
||||||
|
void operator delete(void * ptr);
|
||||||
|
|
||||||
|
__extension__ typedef int __guard __attribute__((mode (__DI__)));
|
||||||
|
|
||||||
|
extern "C" int __cxa_guard_acquire(__guard *);
|
||||||
|
extern "C" void __cxa_guard_release (__guard *);
|
||||||
|
extern "C" void __cxa_guard_abort (__guard *);
|
||||||
|
|
||||||
|
extern "C" void __cxa_pure_virtual(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
321
hardware/digistump/avr/cores/tiny/pins_arduino.c
Normal file
321
hardware/digistump/avr/cores/tiny/pins_arduino.c
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
pins_arduino.c - pin definitions for the Arduino board
|
||||||
|
Part of Arduino / Wiring Lite
|
||||||
|
|
||||||
|
Copyright (c) 2005 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: pins_arduino.c 565 2009-03-25 10:50:00Z dmellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 09-10-2009 for attiny45 A.Saporetti
|
||||||
|
Modified for Atmel ATTiny2313 mcu by René Bohne
|
||||||
|
|
||||||
|
Corrected 17-05-2010 for ATtiny84 B.Cook ...
|
||||||
|
|
||||||
|
The default analog_reference leaves chip pin 13 (digital pin 10; PA0)
|
||||||
|
unconnected. So the pin can be set to a non-floating state and so the
|
||||||
|
pin can be used as another digital pin, support for digital pin 10 was
|
||||||
|
added.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX313__ )
|
||||||
|
|
||||||
|
// On the Arduino board, digital pins are also used
|
||||||
|
// for the analog output (software PWM). Analog input
|
||||||
|
// pins are a separate set.
|
||||||
|
|
||||||
|
// ATMEL ATTINY2313
|
||||||
|
//
|
||||||
|
// +-\/-+
|
||||||
|
// (D 17) PA2 1| |29 VCC
|
||||||
|
// RX (D 0) PD0 2| |19 PB7 (D 16)
|
||||||
|
// TX (D 1) PD1 3| |18 PB6 (D 15)
|
||||||
|
// (D 2) PA1 4| |17 PB5 (D 14)
|
||||||
|
// (D 3) PA0 5| |16 PB4 (D 13)*
|
||||||
|
// INT0 (D 4) PD2 6| |15 PB3 (D 12)*
|
||||||
|
// INT1 (D 5) PD3 7| |14 PB2 (D 11)*
|
||||||
|
// (D 6) PD4 8| |13 PB1 (D 10)
|
||||||
|
// *(D 7) PD5 9| |12 PB0 (D 9)
|
||||||
|
// GND 10| |11 PD6 (D 8)
|
||||||
|
// +----+
|
||||||
|
//
|
||||||
|
// * indicates PWM port
|
||||||
|
|
||||||
|
// these arrays map port names (e.g. port B) to the
|
||||||
|
// appropriate addresses for various functions (e.g. reading
|
||||||
|
// and writing)
|
||||||
|
const uint8_t PROGMEM port_to_mode_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&DDRA,
|
||||||
|
&DDRB,
|
||||||
|
NOT_A_PORT,
|
||||||
|
&DDRD,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_output_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PORTA,
|
||||||
|
&PORTB,
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PORTD,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_input_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PINA,
|
||||||
|
&PINB,
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PIND,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_port_PGM[] =
|
||||||
|
{
|
||||||
|
PORT_D_ID, /* 0 */
|
||||||
|
PORT_D_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_D_ID,
|
||||||
|
PORT_D_ID,
|
||||||
|
PORT_D_ID,
|
||||||
|
PORT_D_ID,
|
||||||
|
PORT_D_ID, /* 8 */
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID, /* 14 */
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
|
||||||
|
{
|
||||||
|
_BV(0), /* 0 */
|
||||||
|
_BV(1),
|
||||||
|
_BV(1),
|
||||||
|
_BV(0),
|
||||||
|
_BV(2),
|
||||||
|
_BV(3),
|
||||||
|
_BV(4),
|
||||||
|
_BV(5),
|
||||||
|
_BV(6), /* 8 */
|
||||||
|
_BV(0),
|
||||||
|
_BV(1),
|
||||||
|
_BV(2),
|
||||||
|
_BV(3),
|
||||||
|
_BV(4),
|
||||||
|
_BV(5), /* 14 */
|
||||||
|
_BV(6),
|
||||||
|
_BV(7),
|
||||||
|
_BV(2),
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
TIMER0B,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
TIMER0A,
|
||||||
|
TIMER1A,
|
||||||
|
TIMER1B,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX4__ )
|
||||||
|
|
||||||
|
// ATMEL ATTINY84 / ARDUINO
|
||||||
|
//
|
||||||
|
// +-\/-+
|
||||||
|
// VCC 1| |14 GND
|
||||||
|
// (D 0) PB0 2| |13 AREF (D 10)
|
||||||
|
// (D 1) PB1 3| |12 PA1 (D 9)
|
||||||
|
// PB3 4| |11 PA2 (D 8)
|
||||||
|
// PWM INT0 (D 2) PB2 5| |10 PA3 (D 7)
|
||||||
|
// PWM (D 3) PA7 6| |9 PA4 (D 6)
|
||||||
|
// PWM (D 4) PA6 7| |8 PA5 (D 5) PWM
|
||||||
|
// +----+
|
||||||
|
|
||||||
|
// these arrays map port names (e.g. port B) to the
|
||||||
|
// appropriate addresses for various functions (e.g. reading
|
||||||
|
// and writing)
|
||||||
|
const uint8_t PROGMEM port_to_mode_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&DDRA,
|
||||||
|
&DDRB,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_output_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PORTA,
|
||||||
|
&PORTB,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_input_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PINA,
|
||||||
|
&PINB,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_pcmask_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PCMSK0,
|
||||||
|
&PCMSK1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_port_PGM[] =
|
||||||
|
{
|
||||||
|
PORT_B_ID, /* 0 */
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_A_ID, /* 8 */
|
||||||
|
PORT_A_ID,
|
||||||
|
PORT_A_ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
|
||||||
|
{
|
||||||
|
_BV(0), /* 0, port B */
|
||||||
|
_BV(1),
|
||||||
|
_BV(2),
|
||||||
|
_BV(7), /* 3 port B */
|
||||||
|
_BV(6),
|
||||||
|
_BV(5),
|
||||||
|
_BV(4),
|
||||||
|
_BV(3),
|
||||||
|
_BV(2),
|
||||||
|
_BV(1),
|
||||||
|
_BV(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
TIMER0A, /* OC0A */
|
||||||
|
TIMER0B, /* OC0B */
|
||||||
|
TIMER1A, /* OC1A */
|
||||||
|
TIMER1B, /* OC1B */
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX5__ )
|
||||||
|
|
||||||
|
// ATMEL ATTINY45 / ARDUINO
|
||||||
|
//
|
||||||
|
// +-\/-+
|
||||||
|
// Ain0 (D 5) PB5 1| |8 VCC
|
||||||
|
// Ain3 (D 3) PB3 2| |7 PB2 (D 2) INT0 Ain1
|
||||||
|
// Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1
|
||||||
|
// GND 4| |5 PB0 (D 0) pwm0
|
||||||
|
// +----+
|
||||||
|
|
||||||
|
// these arrays map port names (e.g. port B) to the
|
||||||
|
// appropriate addresses for various functions (e.g. reading
|
||||||
|
// and writing) tiny45 only port B
|
||||||
|
const uint8_t PROGMEM port_to_mode_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&DDRB,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_output_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PORT,
|
||||||
|
&PORTB,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM port_to_input_PGM[] =
|
||||||
|
{
|
||||||
|
NOT_A_PIN,
|
||||||
|
&PINB,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_port_PGM[] =
|
||||||
|
{
|
||||||
|
PORT_B_ID, /* 0 */
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID,
|
||||||
|
PORT_B_ID, /* 5 */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
|
||||||
|
{
|
||||||
|
_BV(0), /* 0, port B */
|
||||||
|
_BV(1),
|
||||||
|
_BV(2),
|
||||||
|
_BV(3), /* 3 port B */
|
||||||
|
_BV(4),
|
||||||
|
_BV(5),
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
|
||||||
|
{
|
||||||
|
TIMER0A, /* OC0A */
|
||||||
|
TIMER1A, /* OC1A? */
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
NOT_ON_TIMER,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
115
hardware/digistump/avr/cores/tiny/pins_arduino.h
Normal file
115
hardware/digistump/avr/cores/tiny/pins_arduino.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
pins_arduino.h - Pin definition functions for Arduino
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2007 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-10-2009 for attiny45 Saposoft
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX313__ )
|
||||||
|
#define PORT_A_ID 1
|
||||||
|
#define PORT_B_ID 2
|
||||||
|
#define PORT_D_ID 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX4__ )
|
||||||
|
#define PORT_A_ID 1
|
||||||
|
#define PORT_B_ID 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX5__ )
|
||||||
|
#define PORT_B_ID 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NOT_A_PIN 0
|
||||||
|
#define NOT_A_PORT 0
|
||||||
|
|
||||||
|
#define NOT_ON_TIMER 0
|
||||||
|
#define TIMER0A 1
|
||||||
|
#define TIMER0B 2
|
||||||
|
#define TIMER1A 3
|
||||||
|
#define TIMER1B 4
|
||||||
|
|
||||||
|
//changed it to uint16_t to uint8_t
|
||||||
|
extern const uint8_t PROGMEM port_to_mode_PGM[];
|
||||||
|
extern const uint8_t PROGMEM port_to_input_PGM[];
|
||||||
|
extern const uint8_t PROGMEM port_to_output_PGM[];
|
||||||
|
extern const uint8_t PROGMEM port_to_pcmask_PGM[];
|
||||||
|
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
|
||||||
|
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
|
||||||
|
extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
|
||||||
|
|
||||||
|
// Get the bit location within the hardware port of the given virtual pin.
|
||||||
|
// This comes from the pins_*.c file for the active board configuration.
|
||||||
|
//
|
||||||
|
// These perform slightly better as macros compared to inline functions
|
||||||
|
//
|
||||||
|
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
|
||||||
|
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
|
||||||
|
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
|
||||||
|
#define analogInPinToBit(P) (P)
|
||||||
|
// in the following lines modified pgm_read_word in pgm_read_byte, word doesn't work on attiny45
|
||||||
|
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_output_PGM + (P))) )
|
||||||
|
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_input_PGM + (P))) )
|
||||||
|
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_mode_PGM + (P))) )
|
||||||
|
#define portPcMaskRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_pcmask_PGM + (P))) )
|
||||||
|
|
||||||
|
#if defined(__AVR_ATtinyX5__)
|
||||||
|
#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 5) ? (&GIMSK) : ((uint8_t *)NULL))
|
||||||
|
#define digitalPinToPCICRbit(p) (PCIE)
|
||||||
|
#define digitalPinToPCMSK(p) (((p) >= 0 && (p) <= 5) ? (&PCMSK) : ((uint8_t *)NULL))
|
||||||
|
#define digitalPinToPCMSKbit(p) (p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__AVR_ATtinyX4__)
|
||||||
|
#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 10) ? (&GIMSK) : ((uint8_t *)NULL))
|
||||||
|
#define digitalPinToPCICRbit(p) (((p) <= 2) ? PCIE1 : PCIE0)
|
||||||
|
#define digitalPinToPCMSK(p) (((p) <= 2) ? (&PCMSK1) : (((p) <= 10) ? (&PCMSK0) : ((uint8_t *)NULL)))
|
||||||
|
#define digitalPinToPCMSKbit(p) (((p) <= 2) ? (p) : (10 - (p)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__AVR_ATtiny4313__)
|
||||||
|
#define digitalPinToPCX(p,s1,s2,s3,s4,s5) \
|
||||||
|
(((p) >= 0) \
|
||||||
|
? (((p) <= 1) ? (s1) /* 0 - 1 ==> D0 - D1 */ \
|
||||||
|
: (((p) <= 3) ? (s2) /* 2 - 3 ==> A1 - A0 */ \
|
||||||
|
: (((p) <= 8) ? (s3) /* 4 - 8 ==> D2 - D6 */ \
|
||||||
|
: (((p) <= 16) ? (s4) /* 9 - 16 ==> B0 - B7 */ \
|
||||||
|
: (s5))))) \
|
||||||
|
: (s5))
|
||||||
|
// s1 D s2 A s3 D s4 B
|
||||||
|
#define digitalPinToPCICR(p) digitalPinToPCX( p, &GIMSK, &GIMSK, &GIMSK, &GIMSK, NULL )
|
||||||
|
#define digitalPinToPCICRbit(p) digitalPinToPCX( p, PCIE2, PCIE1, PCIE2, PCIE0, 0 )
|
||||||
|
#define digitalPinToPCMSK(p) digitalPinToPCX( p, &PCMSK2, &PCMSK1, &PCMSK2, &PCMSK0, NULL )
|
||||||
|
#define digitalPinToPCMSKbit(p) digitalPinToPCX( p, p, 3-p, p-2, p-9, 0 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
366
hardware/digistump/avr/cores/tiny/wiring.c
Normal file
366
hardware/digistump/avr/cores/tiny/wiring.c
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/*
|
||||||
|
wiring.c - Partial implementation of the Wiring API for the ATmega8.
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 970 2010-05-25 20:16:15Z dmellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-10-2009 for attiny45 Saposoft
|
||||||
|
Modified 20-11-2010 - B.Cook - Rewritten to use the various Veneers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "core_build_options.h"
|
||||||
|
#include "core_adc.h"
|
||||||
|
#include "core_timers.h"
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "ToneTimer.h"
|
||||||
|
#if F_CPU != 16500000L
|
||||||
|
#include <avr/boot.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define millistimer_(t) TIMER_PASTE_A( timer, TIMER_TO_USE_FOR_MILLIS, t )
|
||||||
|
#define MillisTimer_(f) TIMER_PASTE_A( Timer, TIMER_TO_USE_FOR_MILLIS, f )
|
||||||
|
#define MILLISTIMER_(c) TIMER_PASTE_A( TIMER, TIMER_TO_USE_FOR_MILLIS, c )
|
||||||
|
|
||||||
|
#define MillisTimer_SetToPowerup MillisTimer_(SetToPowerup)
|
||||||
|
#define MillisTimer_SetWaveformGenerationMode MillisTimer_(SetWaveformGenerationMode)
|
||||||
|
#define MillisTimer_GetCount MillisTimer_(GetCount)
|
||||||
|
#define MillisTimer_IsOverflowSet MillisTimer_(IsOverflowSet)
|
||||||
|
#define MillisTimer_ClockSelect MillisTimer_(ClockSelect)
|
||||||
|
#define MillisTimer_EnableOverflowInterrupt MillisTimer_(EnableOverflowInterrupt)
|
||||||
|
#define MILLISTIMER_OVF_vect MILLISTIMER_(OVF_vect)
|
||||||
|
|
||||||
|
|
||||||
|
#define MS_TIMER_TICK_EVERY_X_CYCLES 64 /* Shall be a within 1, 8, 64, 256 or 1024. (default = 64) If set to 1, HW PWM is around 64.5KHz@16.5MHz with Digispark */
|
||||||
|
|
||||||
|
#if F_CPU >= 3000000L
|
||||||
|
#if !defined(MS_TIMER_TICK_EVERY_X_CYCLES)
|
||||||
|
#define MillisTimer_Prescale_Index MillisTimer_(Prescale_Value_64)
|
||||||
|
#define MillisTimer_Prescale_Value (64)
|
||||||
|
#define ToneTimer_Prescale_Index ToneTimer_(Prescale_Value_64)
|
||||||
|
#define ToneTimer_Prescale_Value (64)
|
||||||
|
#else
|
||||||
|
#define Prescaler_Value(Val) PRESCALER_VALUE(Val)
|
||||||
|
#define PRESCALER_VALUE(Val) Prescale_Value_##Val
|
||||||
|
#define MillisTimer_Prescale_Index MillisTimer_(Prescaler_Value(MS_TIMER_TICK_EVERY_X_CYCLES))
|
||||||
|
#define MillisTimer_Prescale_Value (MS_TIMER_TICK_EVERY_X_CYCLES)
|
||||||
|
#define ToneTimer_Prescale_Index ToneTimer_(Prescaler_Value(MS_TIMER_TICK_EVERY_X_CYCLES))
|
||||||
|
#define ToneTimer_Prescale_Value (MS_TIMER_TICK_EVERY_X_CYCLES)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define MillisTimer_Prescale_Index MillisTimer_(Prescale_Value_8)
|
||||||
|
#define MillisTimer_Prescale_Value (8)
|
||||||
|
#define ToneTimer_Prescale_Index ToneTimer_(Prescale_Value_8)
|
||||||
|
#define ToneTimer_Prescale_Value (8)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// the prescaler is set so that the millis timer ticks every MillisTimer_Prescale_Value (64) clock cycles, and the
|
||||||
|
// the overflow handler is called every 256 ticks.
|
||||||
|
#define MICROSECONDS_PER_MILLIS_OVERFLOW (clockCyclesToMicroseconds(MillisTimer_Prescale_Value * 256))
|
||||||
|
|
||||||
|
// the whole number of milliseconds per millis timer overflow
|
||||||
|
#define MILLIS_INC (MICROSECONDS_PER_MILLIS_OVERFLOW / 1000)
|
||||||
|
|
||||||
|
// the fractional number of milliseconds per millis timer overflow. we shift right
|
||||||
|
// by three to fit these numbers into a byte. (for the clock speeds we care
|
||||||
|
// about - 8 and 16 MHz - this doesn't lose precision.)
|
||||||
|
#define FRACT_INC ((MICROSECONDS_PER_MILLIS_OVERFLOW % 1000) >> 3)
|
||||||
|
#define FRACT_MAX (1000 >> 3)
|
||||||
|
|
||||||
|
volatile unsigned long millis_timer_overflow_count = 0;
|
||||||
|
volatile unsigned long millis_timer_millis = 0;
|
||||||
|
static unsigned char millis_timer_fract = 0;
|
||||||
|
|
||||||
|
// bluebie changed isr to noblock so it wouldn't mess up USB libraries
|
||||||
|
ISR(MILLISTIMER_OVF_vect, ISR_NOBLOCK)
|
||||||
|
{
|
||||||
|
// copy these to local variables so they can be stored in registers
|
||||||
|
// (volatile variables must be read from memory on every access)
|
||||||
|
unsigned long m = millis_timer_millis;
|
||||||
|
unsigned char f = millis_timer_fract;
|
||||||
|
|
||||||
|
/* rmv: The code below generates considerably less code (emtpy Sketch is 326 versus 304)...
|
||||||
|
|
||||||
|
m += MILLIS_INC;
|
||||||
|
f += FRACT_INC;
|
||||||
|
if (f >= FRACT_MAX) {
|
||||||
|
f -= FRACT_MAX;
|
||||||
|
m += 1;
|
||||||
|
}
|
||||||
|
...rmv */
|
||||||
|
|
||||||
|
f += FRACT_INC;
|
||||||
|
|
||||||
|
if (f >= FRACT_MAX)
|
||||||
|
{
|
||||||
|
f -= FRACT_MAX;
|
||||||
|
m = m + MILLIS_INC + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m += MILLIS_INC;
|
||||||
|
}
|
||||||
|
|
||||||
|
millis_timer_fract = f;
|
||||||
|
millis_timer_millis = m;
|
||||||
|
millis_timer_overflow_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long millis()
|
||||||
|
{
|
||||||
|
unsigned long m;
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
|
||||||
|
// disable interrupts while we read millis_timer_millis or we might get an
|
||||||
|
// inconsistent value (e.g. in the middle of a write to millis_timer_millis)
|
||||||
|
cli();
|
||||||
|
m = millis_timer_millis;
|
||||||
|
SREG = oldSREG;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long micros()
|
||||||
|
{
|
||||||
|
unsigned long m;
|
||||||
|
uint8_t oldSREG = SREG, t;
|
||||||
|
|
||||||
|
cli();
|
||||||
|
m = millis_timer_overflow_count;
|
||||||
|
t = MillisTimer_GetCount();
|
||||||
|
|
||||||
|
if (MillisTimer_IsOverflowSet() && (t < 255))
|
||||||
|
m++;
|
||||||
|
|
||||||
|
SREG = oldSREG;
|
||||||
|
|
||||||
|
#if (MillisTimer_Prescale_Value >= clockCyclesPerMicrosecond())
|
||||||
|
return ((m << 8) + t) * (MillisTimer_Prescale_Value / clockCyclesPerMicrosecond());
|
||||||
|
#else
|
||||||
|
return ((m << 8) + t) / (clockCyclesPerMicrosecond() / MillisTimer_Prescale_Value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay(unsigned long ms)
|
||||||
|
{
|
||||||
|
uint16_t start = (uint16_t)micros();
|
||||||
|
|
||||||
|
while (ms > 0) {
|
||||||
|
if (((uint16_t)micros() - start) >= 1000) {
|
||||||
|
ms--;
|
||||||
|
start += 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if F_CPU == 16500000L
|
||||||
|
// optimised delay loop from Bluebie contributed to Digispark project
|
||||||
|
// deals accurately with half-mhz clock speed, but can only delay in increments of 2us rounded down
|
||||||
|
// this loop has been tuned empirically with an oscilloscope and works in avr-gcc 4.5.1
|
||||||
|
void delayMicroseconds(unsigned int us){
|
||||||
|
us &= ((unsigned int) 0) - ((unsigned int) 2); // remove least signifficant bit
|
||||||
|
while (us > 1) {
|
||||||
|
// 16 nops
|
||||||
|
asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
|
||||||
|
asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
|
||||||
|
// 11 nops
|
||||||
|
asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
|
||||||
|
asm("NOP");asm("NOP");asm("NOP");
|
||||||
|
|
||||||
|
us -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Improved delayMicroseconds function
|
||||||
|
* Copyright (c) 2011, Paul Stoffregen, paul at pjrc dot com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// modified by Bluebie in 2013 for Digispark project
|
||||||
|
// #include <stdint.h>
|
||||||
|
// #include <avr/io.h>
|
||||||
|
|
||||||
|
void delayMicroseconds(uint16_t usec) {
|
||||||
|
asm volatile(
|
||||||
|
#if F_CPU == 16000000L
|
||||||
|
"sbiw %A0, 2" "\n\t" // 2
|
||||||
|
"brcs L_%=_end" "\n\t" // 1
|
||||||
|
"breq L_%=_end" "\n\t" // 1
|
||||||
|
"lsl %A0" "\n\t" // 1
|
||||||
|
"rol %B0" "\n\t" // 1
|
||||||
|
"lsl %A0" "\n\t" // 1
|
||||||
|
"rol %B0" "\n\t" // 1 overhead: (8)/4 = 2us
|
||||||
|
#elif F_CPU == 8000000L
|
||||||
|
"sbiw %A0, 3" "\n\t" // 2
|
||||||
|
"brcs L_%=_end" "\n\t" // 1
|
||||||
|
"breq L_%=_end" "\n\t" // 1
|
||||||
|
"lsl %A0" "\n\t" // 1
|
||||||
|
"rol %B0" "\n\t" // 1 overhead: (6)/2 = 3 us
|
||||||
|
#elif F_CPU == 4000000L
|
||||||
|
"sbiw %A0, 4" "\n\t" // 2
|
||||||
|
"brcs L_%=_end" "\n\t" // 1
|
||||||
|
"breq L_%=_end" "\n\t" // 1 overhead: (4) = 4 us
|
||||||
|
#elif F_CPU == 2000000L
|
||||||
|
"sbiw %A0, 12" "\n\t" // 2
|
||||||
|
"brcs L_%=_end" "\n\t" // 1
|
||||||
|
"breq L_%=_end" "\n\t" // 1
|
||||||
|
"lsr %B0" "\n\t" // 1
|
||||||
|
"ror %A0" "\n\t" // 1 overhead: (6)*2 = 12 us
|
||||||
|
#elif F_CPU == 1000000L
|
||||||
|
"sbiw %A0, 32" "\n\t" // 2
|
||||||
|
"brcs L_%=_end" "\n\t" // 1
|
||||||
|
"breq L_%=_end" "\n\t" // 1
|
||||||
|
"lsr %B0" "\n\t" // 1
|
||||||
|
"ror %A0" "\n\t" // 1
|
||||||
|
"lsr %B0" "\n\t" // 1
|
||||||
|
"ror %A0" "\n\t" // 1 overhead: (8)*4 = 32 us
|
||||||
|
#endif
|
||||||
|
"L_%=_loop:"
|
||||||
|
"sbiw %A0, 1" "\n\t" // 2
|
||||||
|
"brne L_%=_loop" "\n\t" // 2
|
||||||
|
"L_%=_end:"
|
||||||
|
: "+w" (usec)
|
||||||
|
: "0" (usec)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void initToneTimerInternal(void)
|
||||||
|
{
|
||||||
|
// Stop the clock while we make changes
|
||||||
|
ToneTimer_ClockSelect( ToneTimer_(Stopped) );
|
||||||
|
|
||||||
|
// Set the timer to phase-correct PWM
|
||||||
|
#if defined( TONETIMER_SUPPORTS_PHASE_CORRECT_PWM ) && TONETIMER_SUPPORTS_PHASE_CORRECT_PWM
|
||||||
|
ToneTimer_SetWaveformGenerationMode( ToneTimer_(Phase_Correct_PWM_FF) );
|
||||||
|
#else
|
||||||
|
ToneTimer_SetWaveformGenerationMode( ToneTimer_(Fast_PWM_FF) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Timer is processor clock divided by ToneTimer_Prescale_Index (64)
|
||||||
|
ToneTimer_ClockSelect( ToneTimer_Prescale_Index );
|
||||||
|
}
|
||||||
|
|
||||||
|
void initToneTimer(void)
|
||||||
|
{
|
||||||
|
// Ensure the timer is in the same state as power-up
|
||||||
|
ToneTimer_SetToPowerup();
|
||||||
|
|
||||||
|
#if defined( INITIALIZE_SECONDARY_TIMERS ) && INITIALIZE_SECONDARY_TIMERS
|
||||||
|
// Prepare the timer for PWM
|
||||||
|
initToneTimerInternal();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if F_CPU != 16500000L
|
||||||
|
// used to detect bootloader applying calibration in init
|
||||||
|
byte read_factory_calibration(void)
|
||||||
|
{
|
||||||
|
byte SIGRD = 5; // for some reason this isn't defined...
|
||||||
|
byte value = boot_signature_byte_get(1);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void init(void)
|
||||||
|
{
|
||||||
|
// clock calibration stuff
|
||||||
|
// recalibrate clock if it was calibrated by bootloader (like micronucleus)
|
||||||
|
#if F_CPU != 16500000L
|
||||||
|
if (OSCCAL != read_factory_calibration()) {
|
||||||
|
// adjust the calibration down from 16.5mhz to 16.0mhz
|
||||||
|
if (OSCCAL >= 128) {
|
||||||
|
// maybe 8 is better? oh well - only about 0.3% out anyway
|
||||||
|
OSCCAL -= 7;
|
||||||
|
} else {
|
||||||
|
OSCCAL -= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: detect if fuses set to PLL, regular internal oscillator or external and change behaviour in this next section...
|
||||||
|
#if F_CPU < 16000000L
|
||||||
|
cli();
|
||||||
|
CLKPR = 0b10000000;
|
||||||
|
#if F_CPU == 8000000L
|
||||||
|
CLKPR = 1; // div 2
|
||||||
|
#elif F_CPU == 4000000L
|
||||||
|
CLKPR = 2 // div 4
|
||||||
|
#elif F_CPU == 2000000L
|
||||||
|
CLKPR = 3; // div 8
|
||||||
|
#elif F_CPU == 1000000L
|
||||||
|
CLKPR = 4; // div 16
|
||||||
|
#elif F_CPU == 500000L
|
||||||
|
CLKPR = 5; // div 32 = 500khz
|
||||||
|
#elif F_CPU == 250000L
|
||||||
|
CLKPR = 6; // div 64 = 250khz
|
||||||
|
#elif F_CPU == 125000L
|
||||||
|
CLKPR = 7; // div 128 = 125khz cpu clock
|
||||||
|
#else
|
||||||
|
#warning "Cannot prescale chip to specified F_CPU speed"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// this needs to be called before setup() or some functions won't work there
|
||||||
|
sei();
|
||||||
|
|
||||||
|
// In case the bootloader left our millis timer in a bad way
|
||||||
|
#if defined( HAVE_BOOTLOADER ) && HAVE_BOOTLOADER
|
||||||
|
MillisTimer_SetToPowerup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use the Millis Timer for fast PWM
|
||||||
|
MillisTimer_SetWaveformGenerationMode( MillisTimer_(Fast_PWM_FF) );
|
||||||
|
|
||||||
|
// Millis timer is always processor clock divided by MillisTimer_Prescale_Value (64)
|
||||||
|
MillisTimer_ClockSelect( MillisTimer_Prescale_Index );
|
||||||
|
|
||||||
|
// Enable the overlow interrupt (this is the basic system tic-toc for millis)
|
||||||
|
MillisTimer_EnableOverflowInterrupt();
|
||||||
|
|
||||||
|
// Initialize the timer used for Tone
|
||||||
|
#if defined( INITIALIZE_SECONDARY_TIMERS ) && INITIALIZE_SECONDARY_TIMERS
|
||||||
|
initToneTimerInternal();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize the ADC
|
||||||
|
#if defined( INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER ) && INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
|
||||||
|
ADC_PrescalerSelect( ADC_ARDUINO_PRESCALER );
|
||||||
|
ADC_Enable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
194
hardware/digistump/avr/cores/tiny/wiring.h
Normal file
194
hardware/digistump/avr/cores/tiny/wiring.h
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
wiring.h - Partial implementation of the Wiring API for the ATmega8.
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.h 1073 2010-08-17 21:50:41Z dmellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-108-2009 for attiny45 Saposoft
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Wiring_h
|
||||||
|
#define Wiring_h
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "binary.h"
|
||||||
|
#include "core_build_options.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HIGH 0x1
|
||||||
|
#define LOW 0x0
|
||||||
|
|
||||||
|
#define INPUT 0x0
|
||||||
|
#define OUTPUT 0x1
|
||||||
|
|
||||||
|
#define true 0x1
|
||||||
|
#define false 0x0
|
||||||
|
|
||||||
|
#define PI 3.1415926535897932384626433832795
|
||||||
|
#define HALF_PI 1.5707963267948966192313216916398
|
||||||
|
#define TWO_PI 6.283185307179586476925286766559
|
||||||
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
|
|
||||||
|
#define SERIAL 0x0
|
||||||
|
#define DISPLAY 0x1
|
||||||
|
|
||||||
|
#define LSBFIRST 0
|
||||||
|
#define MSBFIRST 1
|
||||||
|
|
||||||
|
#define CHANGE 1
|
||||||
|
#define FALLING 2
|
||||||
|
#define RISING 3
|
||||||
|
|
||||||
|
/* rmv or fix
|
||||||
|
#if defined(__AVR_ATmega1280__)
|
||||||
|
#define INTERNAL1V1 2
|
||||||
|
#define INTERNAL2V56 3
|
||||||
|
#else
|
||||||
|
#define INTERNAL 3
|
||||||
|
#endif
|
||||||
|
#define DEFAULT 1
|
||||||
|
#define EXTERNAL 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* rmv
|
||||||
|
analogReference constants for ATmega168. These are NOT correct for the ATtiny84 nor for the ATtiny85. The correct values are below.
|
||||||
|
|
||||||
|
// Internal 1.1V Voltage Reference with external capacitor at AREF pin
|
||||||
|
#define INTERNAL 3
|
||||||
|
|
||||||
|
// AVCC with external capacitor at AREF pin
|
||||||
|
#define DEFAULT 1
|
||||||
|
|
||||||
|
// AREF, Internal Vref turned off
|
||||||
|
#define EXTERNAL 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined( __AVR_ATtinyX313__ )
|
||||||
|
|
||||||
|
#define DEFAULT (0)
|
||||||
|
|
||||||
|
#elif defined( __AVR_ATtinyX4__ )
|
||||||
|
|
||||||
|
// VCC used as analog reference, disconnected from PA0 (AREF)
|
||||||
|
#define DEFAULT (0)
|
||||||
|
|
||||||
|
// External voltage reference at PA0 (AREF) pin, internal reference turned off
|
||||||
|
#define EXTERNAL (1)
|
||||||
|
|
||||||
|
// Internal 1.1V voltage reference
|
||||||
|
#define INTERNAL (2)
|
||||||
|
|
||||||
|
#elif defined( __AVR_ATtinyX5__ )
|
||||||
|
|
||||||
|
// X 0 0 VCC used as Voltage Reference, disconnected from PB0 (AREF).
|
||||||
|
#define DEFAULT (0)
|
||||||
|
|
||||||
|
// X 0 1 External Voltage Reference at PB0 (AREF) pin, Internal Voltage Reference turned off.
|
||||||
|
#define EXTERNAL (1)
|
||||||
|
|
||||||
|
// 0 1 0 Internal 1.1V Voltage Reference.
|
||||||
|
#define INTERNAL (2)
|
||||||
|
#define INTERNAL1V1 INTERNAL
|
||||||
|
|
||||||
|
// 1 1 1 Internal 2.56V Voltage Reference with external bypass capacitor at PB0 (AREF) pin(1).
|
||||||
|
#define INTERNAL2V56 (7)
|
||||||
|
|
||||||
|
// An alternative for INTERNAL2V56 is (6) ...
|
||||||
|
// 1 1 0 Internal 2.56V Voltage Reference without external bypass capacitor, disconnected from PB0 (AREF)(1).
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// undefine stdlib's abs if encountered
|
||||||
|
#ifdef abs
|
||||||
|
#undef abs
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define min(a,b) ((a)<(b)?(a):(b))
|
||||||
|
#define max(a,b) ((a)>(b)?(a):(b))
|
||||||
|
#define abs(x) ((x)>0?(x):-(x))
|
||||||
|
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||||
|
#if __AVR_LIBC_VERSION__ < 10701UL
|
||||||
|
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||||
|
#endif
|
||||||
|
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||||
|
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||||
|
#define sq(x) ((x)*(x))
|
||||||
|
|
||||||
|
#define interrupts() sei()
|
||||||
|
#define noInterrupts() cli()
|
||||||
|
|
||||||
|
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||||
|
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
|
||||||
|
#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )
|
||||||
|
|
||||||
|
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||||
|
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||||
|
|
||||||
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||||
|
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||||
|
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
|
||||||
|
|
||||||
|
typedef unsigned int word;
|
||||||
|
|
||||||
|
#define bit(b) (1UL << (b))
|
||||||
|
|
||||||
|
typedef uint8_t boolean;
|
||||||
|
typedef uint8_t byte;
|
||||||
|
|
||||||
|
void initToneTimer(void);
|
||||||
|
void init(void);
|
||||||
|
|
||||||
|
void pinMode(uint8_t, uint8_t);
|
||||||
|
void digitalWrite(uint8_t, uint8_t);
|
||||||
|
int digitalRead(uint8_t);
|
||||||
|
int analogRead(uint8_t);
|
||||||
|
void analogReference(uint8_t mode);
|
||||||
|
void analogWrite(uint8_t, int);
|
||||||
|
|
||||||
|
unsigned long millis(void);
|
||||||
|
unsigned long micros(void);
|
||||||
|
void delay(unsigned long);
|
||||||
|
void delayMicroseconds(unsigned int us);
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
|
||||||
|
|
||||||
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
|
||||||
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
||||||
|
|
||||||
|
void attachInterrupt(uint8_t, void (*)(void), int mode);
|
||||||
|
void detachInterrupt(uint8_t);
|
||||||
|
|
||||||
|
void setup(void);
|
||||||
|
void loop(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
140
hardware/digistump/avr/cores/tiny/wiring_analog.c
Normal file
140
hardware/digistump/avr/cores/tiny/wiring_analog.c
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
wiring_analog.c - analog input and output
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-10-2009 for attiny45 Saposoft
|
||||||
|
Corrected 17-05-2010 for ATtiny84 B.Cook
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#include "core_adc.h"
|
||||||
|
#include "core_pins.h"
|
||||||
|
#include "core_timers.h"
|
||||||
|
#include "PwmTimer.h"
|
||||||
|
|
||||||
|
uint8_t analog_reference = DEFAULT;
|
||||||
|
|
||||||
|
void analogReference(uint8_t mode)
|
||||||
|
{
|
||||||
|
// can't actually set the register here because the default setting
|
||||||
|
// will connect AVCC and the AREF pin, which would cause a short if
|
||||||
|
// there's something connected to AREF.
|
||||||
|
// fix? Validate the mode?
|
||||||
|
analog_reference = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int analogRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
#if defined( CORE_ANALOG_FIRST )
|
||||||
|
if ( pin >= CORE_ANALOG_FIRST ) pin -= CORE_ANALOG_FIRST; // allow for channel or pin numbers
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// fix? Validate pin?
|
||||||
|
|
||||||
|
ADC_SetVoltageReference( analog_reference );
|
||||||
|
ADC_SetInputChannel( pin );
|
||||||
|
|
||||||
|
ADC_StartConversion();
|
||||||
|
|
||||||
|
while( ADC_ConversionInProgress() );
|
||||||
|
|
||||||
|
return( ADC_GetDataRegister() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right now, PWM output only works on the pins with
|
||||||
|
// hardware support. These are defined in the appropriate
|
||||||
|
// pins_*.c file. For the rest of the pins, we default
|
||||||
|
// to digital output.
|
||||||
|
void analogWrite(uint8_t pin, int val)
|
||||||
|
{
|
||||||
|
// We need to make sure the PWM output is enabled for those pins
|
||||||
|
// that support it, as we turn it off when digitally reading or
|
||||||
|
// writing with them. Also, make sure the pin is in output mode
|
||||||
|
// for consistenty with Wiring, which doesn't require a pinMode
|
||||||
|
// call for the analog output pins.
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
|
||||||
|
if (val <= 0)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
else if (val >= 255)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if CORE_PWM_COUNT >= 1
|
||||||
|
if ( pin == CORE_PWM0_PIN )
|
||||||
|
{
|
||||||
|
Pwm0_SetCompareOutputMode( Pwm0_Clear );
|
||||||
|
Pwm0_SetOutputCompareMatch( val );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 2
|
||||||
|
if ( pin == CORE_PWM1_PIN )
|
||||||
|
{
|
||||||
|
Pwm1_SetCompareOutputMode( Pwm1_Clear );
|
||||||
|
Pwm1_SetOutputCompareMatch( val );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 3
|
||||||
|
if ( pin == CORE_PWM2_PIN )
|
||||||
|
{
|
||||||
|
Pwm2_SetCompareOutputMode( Pwm2_Clear );
|
||||||
|
Pwm2_SetOutputCompareMatch( val );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 4
|
||||||
|
if ( pin == CORE_PWM3_PIN )
|
||||||
|
{
|
||||||
|
Pwm3_SetCompareOutputMode( Pwm3_Clear );
|
||||||
|
Pwm3_SetOutputCompareMatch( val );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 5
|
||||||
|
#error Only 4 PWM pins are supported. Add more conditions.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
if (val < 128)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
148
hardware/digistump/avr/cores/tiny/wiring_digital.c
Normal file
148
hardware/digistump/avr/cores/tiny/wiring_digital.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
wiring_digital.c - digital input and output functions
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
Modified 14-10-2009 for attiny45 Saposoft
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#include "core_pins.h"
|
||||||
|
#include "core_timers.h"
|
||||||
|
#include "PwmTimer.h"
|
||||||
|
|
||||||
|
void pinMode(uint8_t pin, uint8_t mode)
|
||||||
|
{
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
volatile uint8_t *reg;
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN) return;
|
||||||
|
|
||||||
|
// JWS: can I let the optimizer do this?
|
||||||
|
reg = portModeRegister(port);
|
||||||
|
|
||||||
|
if (mode == INPUT) {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*reg &= ~bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
} else {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*reg |= bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forcing this inline keeps the callers from having to push their own stuff
|
||||||
|
// on the stack. It is a good performance win and only takes 1 more byte per
|
||||||
|
// user than calling. (It will take more bytes on the 168.)
|
||||||
|
//
|
||||||
|
// But shouldn't this be moved into pinMode? Seems silly to check and do on
|
||||||
|
// each digitalread or write.
|
||||||
|
//
|
||||||
|
__attribute__((always_inline)) static inline void turnOffPWM( uint8_t pin )
|
||||||
|
{
|
||||||
|
#if CORE_PWM_COUNT >= 1
|
||||||
|
if ( pin == CORE_PWM0_PIN )
|
||||||
|
{
|
||||||
|
Pwm0_SetCompareOutputMode( Pwm0_Disconnected );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 2
|
||||||
|
if ( pin == CORE_PWM1_PIN )
|
||||||
|
{
|
||||||
|
Pwm1_SetCompareOutputMode( Pwm1_Disconnected );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 3
|
||||||
|
if ( pin == CORE_PWM2_PIN )
|
||||||
|
{
|
||||||
|
Pwm2_SetCompareOutputMode( Pwm2_Disconnected );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 4
|
||||||
|
if ( pin == CORE_PWM3_PIN )
|
||||||
|
{
|
||||||
|
Pwm3_SetCompareOutputMode( Pwm3_Disconnected );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CORE_PWM_COUNT >= 5
|
||||||
|
#error Only 4 PWM pins are supported. Add more conditions.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void digitalWrite(uint8_t pin, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
volatile uint8_t *out;
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN) return;
|
||||||
|
|
||||||
|
// If the pin that support PWM output, we need to turn it off
|
||||||
|
// before doing a digital write.
|
||||||
|
turnOffPWM( pin );
|
||||||
|
|
||||||
|
out = portOutputRegister(port);
|
||||||
|
|
||||||
|
if (val == LOW) {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*out &= ~bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
} else {
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
*out |= bit;
|
||||||
|
SREG = oldSREG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int digitalRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
|
||||||
|
if (port == NOT_A_PIN) return LOW;
|
||||||
|
|
||||||
|
// If the pin that support PWM output, we need to turn it off
|
||||||
|
// before getting a digital reading.
|
||||||
|
turnOffPWM( pin );
|
||||||
|
|
||||||
|
if (*portInputRegister(port) & bit) return HIGH;
|
||||||
|
return LOW;
|
||||||
|
}
|
179
hardware/digistump/avr/cores/tiny/wiring_private.h
Normal file
179
hardware/digistump/avr/cores/tiny/wiring_private.h
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
wiring_private.h - Internal header file.
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
|
||||||
|
|
||||||
|
Modified 28-08-2009 for attiny84 R.Wiersma
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WiringPrivate_h
|
||||||
|
#define WiringPrivate_h
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/delay.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "wiring.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef cbi
|
||||||
|
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||||
|
#endif
|
||||||
|
#ifndef sbi
|
||||||
|
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT0_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_0_vect EXT_INT0_vect
|
||||||
|
#elif defined( INT0_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_0_vect INT0_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT1_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_1_vect EXT_INT1_vect
|
||||||
|
#elif defined( INT1_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_1_vect INT1_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT2_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_2_vect EXT_INT2_vect
|
||||||
|
#elif defined( INT2_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_2_vect INT2_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT3_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_3_vect EXT_INT3_vect
|
||||||
|
#elif defined( INT3_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_3_vect INT3_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT4_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_4_vect EXT_INT4_vect
|
||||||
|
#elif defined( INT4_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_4_vect INT4_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT5_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_5_vect EXT_INT5_vect
|
||||||
|
#elif defined( INT5_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_5_vect INT5_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT6_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_6_vect EXT_INT6_vect
|
||||||
|
#elif defined( INT6_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_6_vect INT6_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT7_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_7_vect EXT_INT7_vect
|
||||||
|
#elif defined( INT7_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_7_vect INT7_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT8_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_8_vect EXT_INT8_vect
|
||||||
|
#elif defined( INT8_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_8_vect INT8_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXT_INT9_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_9_vect EXT_INT9_vect
|
||||||
|
#elif defined( INT9_vect )
|
||||||
|
#define EXTERNAL_INTERRUPT_9_vect INT9_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( EXTERNAL_INTERRUPT_9_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (10)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_8_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (9)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_7_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (8)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_6_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (7)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_5_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (6)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_4_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (5)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_3_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (4)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_2_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (3)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_1_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (2)
|
||||||
|
#elif defined( EXTERNAL_INTERRUPT_0_vect )
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (1)
|
||||||
|
#else
|
||||||
|
#define NUMBER_EXTERNAL_INTERRUPTS (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 1
|
||||||
|
#define EXTERNAL_INTERRUPT_0 (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 2
|
||||||
|
#define EXTERNAL_INTERRUPT_1 (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 3
|
||||||
|
#define EXTERNAL_INTERRUPT_2 (2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 4
|
||||||
|
#define EXTERNAL_INTERRUPT_3 (3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 5
|
||||||
|
#define EXTERNAL_INTERRUPT_4 (4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 6
|
||||||
|
#define EXTERNAL_INTERRUPT_5 (5)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 7
|
||||||
|
#define EXTERNAL_INTERRUPT_6 (6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 8
|
||||||
|
#define EXTERNAL_INTERRUPT_7 (7)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 9
|
||||||
|
#define EXTERNAL_INTERRUPT_8 (8)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NUMBER_EXTERNAL_INTERRUPTS >= 10
|
||||||
|
#define EXTERNAL_INTERRUPT_9 (9)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*voidFuncPtr)(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
69
hardware/digistump/avr/cores/tiny/wiring_pulse.c
Normal file
69
hardware/digistump/avr/cores/tiny/wiring_pulse.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
wiring_pulse.c - pulseIn() function
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
|
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
|
||||||
|
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
|
||||||
|
* to 3 minutes in length, but must be called at least a few dozen microseconds
|
||||||
|
* before the start of the pulse. */
|
||||||
|
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
|
||||||
|
{
|
||||||
|
// cache the port and bit of the pin in order to speed up the
|
||||||
|
// pulse width measuring loop and achieve finer resolution. calling
|
||||||
|
// digitalRead() instead yields much coarser resolution.
|
||||||
|
uint8_t bit = digitalPinToBitMask(pin);
|
||||||
|
uint8_t port = digitalPinToPort(pin);
|
||||||
|
uint8_t stateMask = (state ? bit : 0);
|
||||||
|
unsigned long width = 0; // keep initialization out of time critical area
|
||||||
|
|
||||||
|
// convert the timeout from microseconds to a number of times through
|
||||||
|
// the initial loop; it takes 16 clock cycles per iteration.
|
||||||
|
unsigned long numloops = 0;
|
||||||
|
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
|
||||||
|
|
||||||
|
// wait for any previous pulse to end
|
||||||
|
while ((*portInputRegister(port) & bit) == stateMask)
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// wait for the pulse to start
|
||||||
|
while ((*portInputRegister(port) & bit) != stateMask)
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// wait for the pulse to stop
|
||||||
|
while ((*portInputRegister(port) & bit) == stateMask) {
|
||||||
|
if (numloops++ == maxloops)
|
||||||
|
return 0;
|
||||||
|
width++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the reading to microseconds. The loop has been determined
|
||||||
|
// to be 20 clock cycles long and have about 16 clocks between the edge
|
||||||
|
// and the start of the loop. There will be some error introduced by
|
||||||
|
// the interrupt handlers.
|
||||||
|
return clockCyclesToMicroseconds(width * 21 + 16);
|
||||||
|
}
|
55
hardware/digistump/avr/cores/tiny/wiring_shift.c
Normal file
55
hardware/digistump/avr/cores/tiny/wiring_shift.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
wiring_shift.c - shiftOut() function
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2006 David A. Mellis
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wiring_private.h"
|
||||||
|
|
||||||
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
|
||||||
|
uint8_t value = 0;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
digitalWrite(clockPin, HIGH);
|
||||||
|
if (bitOrder == LSBFIRST)
|
||||||
|
value |= digitalRead(dataPin) << i;
|
||||||
|
else
|
||||||
|
value |= digitalRead(dataPin) << (7 - i);
|
||||||
|
digitalWrite(clockPin, LOW);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (bitOrder == LSBFIRST)
|
||||||
|
digitalWrite(dataPin, !!(val & (1 << i)));
|
||||||
|
else
|
||||||
|
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
|
||||||
|
|
||||||
|
digitalWrite(clockPin, HIGH);
|
||||||
|
digitalWrite(clockPin, LOW);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,937 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Arduino library to control a wide variety of WS2811- and WS2812-based RGB
|
||||||
|
LED devices such as Adafruit FLORA RGB Smart Pixels and NeoPixel strips.
|
||||||
|
Currently handles 400 and 800 KHz bitstreams on 8, 12 and 16 MHz ATmega
|
||||||
|
MCUs, with LEDs wired for RGB or GRB color order. 8 MHz MCUs provide
|
||||||
|
output on PORTB and PORTD, while 16 MHz chips can handle most output pins
|
||||||
|
(possible exception with upper PORT registers on the Arduino Mega).
|
||||||
|
|
||||||
|
Written by Phil Burgess / Paint Your Dragon for Adafruit Industries,
|
||||||
|
contributions by PJRC and other members of the open source community.
|
||||||
|
|
||||||
|
Adafruit invests time and resources providing this open source code,
|
||||||
|
please support Adafruit and open-source hardware by purchasing products
|
||||||
|
from Adafruit!
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
This file is part of the Adafruit NeoPixel library.
|
||||||
|
|
||||||
|
NeoPixel is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
NeoPixel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with NeoPixel. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "Adafruit_NeoPixel.h"
|
||||||
|
|
||||||
|
Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, uint8_t p, uint8_t t) : numLEDs(n), numBytes(n * 3), pin(p), pixels(NULL)
|
||||||
|
,type(t), brightness(0), endTime(0)
|
||||||
|
#ifdef __AVR__
|
||||||
|
,port(portOutputRegister(digitalPinToPort(p))),
|
||||||
|
pinMask(digitalPinToBitMask(p))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if((pixels = (uint8_t *)malloc(numBytes))) {
|
||||||
|
memset(pixels, 0, numBytes);
|
||||||
|
}
|
||||||
|
if(t & NEO_GRB) { // GRB vs RGB; might add others if needed
|
||||||
|
rOffset = 1;
|
||||||
|
gOffset = 0;
|
||||||
|
bOffset = 2;
|
||||||
|
} else if (t & NEO_BRG) {
|
||||||
|
rOffset = 1;
|
||||||
|
gOffset = 2;
|
||||||
|
bOffset = 0;
|
||||||
|
} else {
|
||||||
|
rOffset = 0;
|
||||||
|
gOffset = 1;
|
||||||
|
bOffset = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Adafruit_NeoPixel::~Adafruit_NeoPixel() {
|
||||||
|
if(pixels) free(pixels);
|
||||||
|
pinMode(pin, INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_NeoPixel::begin(void) {
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_NeoPixel::show(void) {
|
||||||
|
|
||||||
|
if(!pixels) return;
|
||||||
|
|
||||||
|
// Data latch = 50+ microsecond pause in the output stream. Rather than
|
||||||
|
// put a delay at the end of the function, the ending time is noted and
|
||||||
|
// the function will simply hold off (if needed) on issuing the
|
||||||
|
// subsequent round of data until the latch time has elapsed. This
|
||||||
|
// allows the mainline code to start generating the next frame of data
|
||||||
|
// rather than stalling for the latch.
|
||||||
|
while(!canShow());
|
||||||
|
// endTime is a private member (rather than global var) so that mutliple
|
||||||
|
// instances on different pins can be quickly issued in succession (each
|
||||||
|
// instance doesn't delay the next).
|
||||||
|
|
||||||
|
// In order to make this code runtime-configurable to work with any pin,
|
||||||
|
// SBI/CBI instructions are eschewed in favor of full PORT writes via the
|
||||||
|
// OUT or ST instructions. It relies on two facts: that peripheral
|
||||||
|
// functions (such as PWM) take precedence on output pins, so our PORT-
|
||||||
|
// wide writes won't interfere, and that interrupts are globally disabled
|
||||||
|
// while data is being issued to the LEDs, so no other code will be
|
||||||
|
// accessing the PORT. The code takes an initial 'snapshot' of the PORT
|
||||||
|
// state, computes 'pin high' and 'pin low' values, and writes these back
|
||||||
|
// to the PORT register as needed.
|
||||||
|
|
||||||
|
noInterrupts(); // Need 100% focus on instruction timing
|
||||||
|
|
||||||
|
#ifdef __AVR__
|
||||||
|
|
||||||
|
volatile uint16_t
|
||||||
|
i = numBytes; // Loop counter
|
||||||
|
volatile uint8_t
|
||||||
|
*ptr = pixels, // Pointer to next byte
|
||||||
|
b = *ptr++, // Current byte value
|
||||||
|
hi, // PORT w/output bit set high
|
||||||
|
lo; // PORT w/output bit set low
|
||||||
|
|
||||||
|
// Hand-tuned assembly code issues data to the LED drivers at a specific
|
||||||
|
// rate. There's separate code for different CPU speeds (8, 12, 16 MHz)
|
||||||
|
// for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The
|
||||||
|
// datastream timing for the LED drivers allows a little wiggle room each
|
||||||
|
// way (listed in the datasheets), so the conditions for compiling each
|
||||||
|
// case are set up for a range of frequencies rather than just the exact
|
||||||
|
// 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on
|
||||||
|
// devices (e.g. 16.5 MHz DigiSpark). The ranges were arrived at based
|
||||||
|
// on the datasheet figures and have not been extensively tested outside
|
||||||
|
// the canonical 8/12/16 MHz speeds; there's no guarantee these will work
|
||||||
|
// close to the extremes (or possibly they could be pushed further).
|
||||||
|
// Keep in mind only one CPU speed case actually gets compiled; the
|
||||||
|
// resulting program isn't as massive as it might look from source here.
|
||||||
|
|
||||||
|
// 8 MHz(ish) AVR ---------------------------------------------------------
|
||||||
|
#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
|
||||||
|
#endif
|
||||||
|
|
||||||
|
volatile uint8_t n1, n2 = 0; // First, next bits out
|
||||||
|
|
||||||
|
// Squeezing an 800 KHz stream out of an 8 MHz chip requires code
|
||||||
|
// specific to each PORT register. At present this is only written
|
||||||
|
// to work with pins on PORTD or PORTB, the most likely use case --
|
||||||
|
// this covers all the pins on the Adafruit Flora and the bulk of
|
||||||
|
// digital pins on the Arduino Pro 8 MHz (keep in mind, this code
|
||||||
|
// doesn't even get compiled for 16 MHz boards like the Uno, Mega,
|
||||||
|
// Leonardo, etc., so don't bother extending this out of hand).
|
||||||
|
// Additional PORTs could be added if you really need them, just
|
||||||
|
// duplicate the else and loop and change the PORT. Each add'l
|
||||||
|
// PORT will require about 150(ish) bytes of program space.
|
||||||
|
|
||||||
|
// 10 instruction clocks per bit: HHxxxxxLLL
|
||||||
|
// OUT instructions: ^ ^ ^ (T=0,2,7)
|
||||||
|
|
||||||
|
#ifdef PORTD // PORTD isn't present on ATtiny85, etc.
|
||||||
|
|
||||||
|
if(port == &PORTD) {
|
||||||
|
|
||||||
|
hi = PORTD | pinMask;
|
||||||
|
lo = PORTD & ~pinMask;
|
||||||
|
n1 = lo;
|
||||||
|
if(b & 0x80) n1 = hi;
|
||||||
|
|
||||||
|
// Dirty trick: RJMPs proceeding to the next instruction are used
|
||||||
|
// to delay two clock cycles in one instruction word (rather than
|
||||||
|
// using two NOPs). This was necessary in order to squeeze the
|
||||||
|
// loop down to exactly 64 words -- the maximum possible for a
|
||||||
|
// relative branch.
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"headD:" "\n\t" // Clk Pseudocode
|
||||||
|
// Bit 7:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
|
||||||
|
"out %[port] , %[n1]" "\n\t" // 1 PORT = n1
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
"sbrc %[byte] , 6" "\n\t" // 1-2 if(b & 0x40)
|
||||||
|
"mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
// Bit 6:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
|
||||||
|
"out %[port] , %[n2]" "\n\t" // 1 PORT = n2
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
"sbrc %[byte] , 5" "\n\t" // 1-2 if(b & 0x20)
|
||||||
|
"mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
// Bit 5:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
|
||||||
|
"out %[port] , %[n1]" "\n\t" // 1 PORT = n1
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
"sbrc %[byte] , 4" "\n\t" // 1-2 if(b & 0x10)
|
||||||
|
"mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
// Bit 4:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
|
||||||
|
"out %[port] , %[n2]" "\n\t" // 1 PORT = n2
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
"sbrc %[byte] , 3" "\n\t" // 1-2 if(b & 0x08)
|
||||||
|
"mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
// Bit 3:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
|
||||||
|
"out %[port] , %[n1]" "\n\t" // 1 PORT = n1
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
"sbrc %[byte] , 2" "\n\t" // 1-2 if(b & 0x04)
|
||||||
|
"mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
// Bit 2:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
|
||||||
|
"out %[port] , %[n2]" "\n\t" // 1 PORT = n2
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
"sbrc %[byte] , 1" "\n\t" // 1-2 if(b & 0x02)
|
||||||
|
"mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
// Bit 1:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
|
||||||
|
"out %[port] , %[n1]" "\n\t" // 1 PORT = n1
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop
|
||||||
|
"sbrc %[byte] , 0" "\n\t" // 1-2 if(b & 0x01)
|
||||||
|
"mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet)
|
||||||
|
// Bit 0:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi
|
||||||
|
"mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
|
||||||
|
"out %[port] , %[n2]" "\n\t" // 1 PORT = n2
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++
|
||||||
|
"sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80)
|
||||||
|
"mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo
|
||||||
|
"brne headD" "\n" // 2 while(i) (Z flag set above)
|
||||||
|
: [byte] "+r" (b),
|
||||||
|
[n1] "+r" (n1),
|
||||||
|
[n2] "+r" (n2),
|
||||||
|
[count] "+w" (i)
|
||||||
|
: [port] "I" (_SFR_IO_ADDR(PORTD)),
|
||||||
|
[ptr] "e" (ptr),
|
||||||
|
[hi] "r" (hi),
|
||||||
|
[lo] "r" (lo));
|
||||||
|
|
||||||
|
} else if(port == &PORTB) {
|
||||||
|
|
||||||
|
#endif // PORTD
|
||||||
|
|
||||||
|
// Same as above, just switched to PORTB and stripped of comments.
|
||||||
|
hi = PORTB | pinMask;
|
||||||
|
lo = PORTB & ~pinMask;
|
||||||
|
n1 = lo;
|
||||||
|
if(b & 0x80) n1 = hi;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"headB:" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n2] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n1]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"sbrc %[byte] , 6" "\n\t"
|
||||||
|
"mov %[n2] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n1] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n2]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"sbrc %[byte] , 5" "\n\t"
|
||||||
|
"mov %[n1] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n2] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n1]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"sbrc %[byte] , 4" "\n\t"
|
||||||
|
"mov %[n2] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n1] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n2]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"sbrc %[byte] , 3" "\n\t"
|
||||||
|
"mov %[n1] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n2] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n1]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"sbrc %[byte] , 2" "\n\t"
|
||||||
|
"mov %[n2] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n1] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n2]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"sbrc %[byte] , 1" "\n\t"
|
||||||
|
"mov %[n1] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n2] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n1]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"sbrc %[byte] , 0" "\n\t"
|
||||||
|
"mov %[n2] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"sbiw %[count], 1" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"mov %[n1] , %[lo]" "\n\t"
|
||||||
|
"out %[port] , %[n2]" "\n\t"
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t"
|
||||||
|
"sbrc %[byte] , 7" "\n\t"
|
||||||
|
"mov %[n1] , %[hi]" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"brne headB" "\n"
|
||||||
|
: [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
|
||||||
|
: [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
|
||||||
|
[lo] "r" (lo));
|
||||||
|
|
||||||
|
#ifdef PORTD
|
||||||
|
} // endif PORTB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
} else { // end 800 KHz, do 400 KHz
|
||||||
|
|
||||||
|
// Timing is more relaxed; unrolling the inner loop for each bit is
|
||||||
|
// not necessary. Still using the peculiar RJMPs as 2X NOPs, not out
|
||||||
|
// of need but just to trim the code size down a little.
|
||||||
|
// This 400-KHz-datastream-on-8-MHz-CPU code is not quite identical
|
||||||
|
// to the 800-on-16 code later -- the hi/lo timing between WS2811 and
|
||||||
|
// WS2812 is not simply a 2:1 scale!
|
||||||
|
|
||||||
|
// 20 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL
|
||||||
|
// ST instructions: ^ ^ ^ (T=0,4,10)
|
||||||
|
|
||||||
|
volatile uint8_t next, bit;
|
||||||
|
|
||||||
|
hi = *port | pinMask;
|
||||||
|
lo = *port & ~pinMask;
|
||||||
|
next = lo;
|
||||||
|
bit = 8;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"head20:" "\n\t" // Clk Pseudocode (T = 0)
|
||||||
|
"st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
|
||||||
|
"sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
|
||||||
|
"mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
|
||||||
|
"st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 6)
|
||||||
|
"mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
|
||||||
|
"dec %[bit]" "\n\t" // 1 bit-- (T = 8)
|
||||||
|
"breq nextbyte20" "\n\t" // 1-2 if(bit == 0)
|
||||||
|
"rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
|
||||||
|
"st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 14)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 16)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 18)
|
||||||
|
"rjmp head20" "\n\t" // 2 -> head20 (next bit out)
|
||||||
|
"nextbyte20:" "\n\t" // (T = 10)
|
||||||
|
"st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 13)
|
||||||
|
"ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 14)
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 16)
|
||||||
|
"sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
|
||||||
|
"brne head20" "\n" // 2 if(i != 0) -> (next byte)
|
||||||
|
: [port] "+e" (port),
|
||||||
|
[byte] "+r" (b),
|
||||||
|
[bit] "+r" (bit),
|
||||||
|
[next] "+r" (next),
|
||||||
|
[count] "+w" (i)
|
||||||
|
: [hi] "r" (hi),
|
||||||
|
[lo] "r" (lo),
|
||||||
|
[ptr] "e" (ptr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 12 MHz(ish) AVR --------------------------------------------------------
|
||||||
|
#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// In the 12 MHz case, an optimized 800 KHz datastream (no dead time
|
||||||
|
// between bytes) requires a PORT-specific loop similar to the 8 MHz
|
||||||
|
// code (but a little more relaxed in this case).
|
||||||
|
|
||||||
|
// 15 instruction clocks per bit: HHHHxxxxxxLLLLL
|
||||||
|
// OUT instructions: ^ ^ ^ (T=0,4,10)
|
||||||
|
|
||||||
|
volatile uint8_t next;
|
||||||
|
|
||||||
|
#ifdef PORTD
|
||||||
|
|
||||||
|
if(port == &PORTD) {
|
||||||
|
|
||||||
|
hi = PORTD | pinMask;
|
||||||
|
lo = PORTD & ~pinMask;
|
||||||
|
next = lo;
|
||||||
|
if(b & 0x80) next = hi;
|
||||||
|
|
||||||
|
// Don't "optimize" the OUT calls into the bitTime subroutine;
|
||||||
|
// we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
|
||||||
|
asm volatile(
|
||||||
|
"headD:" "\n\t" // (T = 0)
|
||||||
|
"out %[port], %[hi]" "\n\t" // (T = 1)
|
||||||
|
"rcall bitTimeD" "\n\t" // Bit 7 (T = 15)
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeD" "\n\t" // Bit 6
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeD" "\n\t" // Bit 5
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeD" "\n\t" // Bit 4
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeD" "\n\t" // Bit 3
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeD" "\n\t" // Bit 2
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeD" "\n\t" // Bit 1
|
||||||
|
// Bit 0:
|
||||||
|
"out %[port] , %[hi]" "\n\t" // 1 PORT = hi (T = 1)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 3)
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 5)
|
||||||
|
"out %[port] , %[next]" "\n\t" // 1 PORT = next (T = 6)
|
||||||
|
"mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
|
||||||
|
"sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
|
||||||
|
"mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9)
|
||||||
|
"nop" "\n\t" // 1 (T = 10)
|
||||||
|
"out %[port] , %[lo]" "\n\t" // 1 PORT = lo (T = 11)
|
||||||
|
"sbiw %[count], 1" "\n\t" // 2 i-- (T = 13)
|
||||||
|
"brne headD" "\n\t" // 2 if(i != 0) -> (next byte)
|
||||||
|
"rjmp doneD" "\n\t"
|
||||||
|
"bitTimeD:" "\n\t" // nop nop nop (T = 4)
|
||||||
|
"out %[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
|
||||||
|
"mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6)
|
||||||
|
"rol %[byte]" "\n\t" // 1 b <<= 1 (T = 7)
|
||||||
|
"sbrc %[byte], 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
|
||||||
|
"mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9)
|
||||||
|
"nop" "\n\t" // 1 (T = 10)
|
||||||
|
"out %[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11)
|
||||||
|
"ret" "\n\t" // 4 nop nop nop nop (T = 15)
|
||||||
|
"doneD:" "\n"
|
||||||
|
: [byte] "+r" (b),
|
||||||
|
[next] "+r" (next),
|
||||||
|
[count] "+w" (i)
|
||||||
|
: [port] "I" (_SFR_IO_ADDR(PORTD)),
|
||||||
|
[ptr] "e" (ptr),
|
||||||
|
[hi] "r" (hi),
|
||||||
|
[lo] "r" (lo));
|
||||||
|
|
||||||
|
} else if(port == &PORTB) {
|
||||||
|
|
||||||
|
#endif // PORTD
|
||||||
|
|
||||||
|
hi = PORTB | pinMask;
|
||||||
|
lo = PORTB & ~pinMask;
|
||||||
|
next = lo;
|
||||||
|
if(b & 0x80) next = hi;
|
||||||
|
|
||||||
|
// Same as above, just set for PORTB & stripped of comments
|
||||||
|
asm volatile(
|
||||||
|
"headB:" "\n\t"
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeB" "\n\t"
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeB" "\n\t"
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeB" "\n\t"
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeB" "\n\t"
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeB" "\n\t"
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeB" "\n\t"
|
||||||
|
"out %[port], %[hi]" "\n\t"
|
||||||
|
"rcall bitTimeB" "\n\t"
|
||||||
|
"out %[port] , %[hi]" "\n\t"
|
||||||
|
"rjmp .+0" "\n\t"
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t"
|
||||||
|
"out %[port] , %[next]" "\n\t"
|
||||||
|
"mov %[next] , %[lo]" "\n\t"
|
||||||
|
"sbrc %[byte] , 7" "\n\t"
|
||||||
|
"mov %[next] , %[hi]" "\n\t"
|
||||||
|
"nop" "\n\t"
|
||||||
|
"out %[port] , %[lo]" "\n\t"
|
||||||
|
"sbiw %[count], 1" "\n\t"
|
||||||
|
"brne headB" "\n\t"
|
||||||
|
"rjmp doneB" "\n\t"
|
||||||
|
"bitTimeB:" "\n\t"
|
||||||
|
"out %[port], %[next]" "\n\t"
|
||||||
|
"mov %[next], %[lo]" "\n\t"
|
||||||
|
"rol %[byte]" "\n\t"
|
||||||
|
"sbrc %[byte], 7" "\n\t"
|
||||||
|
"mov %[next], %[hi]" "\n\t"
|
||||||
|
"nop" "\n\t"
|
||||||
|
"out %[port], %[lo]" "\n\t"
|
||||||
|
"ret" "\n\t"
|
||||||
|
"doneB:" "\n"
|
||||||
|
: [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
|
||||||
|
: [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
|
||||||
|
[lo] "r" (lo));
|
||||||
|
|
||||||
|
#ifdef PORTD
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
} else { // 400 KHz
|
||||||
|
|
||||||
|
// 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL
|
||||||
|
// ST instructions: ^ ^ ^ (T=0,6,15)
|
||||||
|
|
||||||
|
volatile uint8_t next, bit;
|
||||||
|
|
||||||
|
hi = *port | pinMask;
|
||||||
|
lo = *port & ~pinMask;
|
||||||
|
next = lo;
|
||||||
|
bit = 8;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"head30:" "\n\t" // Clk Pseudocode (T = 0)
|
||||||
|
"st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
|
||||||
|
"sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
|
||||||
|
"mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 6)
|
||||||
|
"st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 8)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 10)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 12)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 14)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 15)
|
||||||
|
"st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 17)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 19)
|
||||||
|
"dec %[bit]" "\n\t" // 1 bit-- (T = 20)
|
||||||
|
"breq nextbyte30" "\n\t" // 1-2 if(bit == 0)
|
||||||
|
"rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 24)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 26)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 28)
|
||||||
|
"rjmp head30" "\n\t" // 2 -> head30 (next bit out)
|
||||||
|
"nextbyte30:" "\n\t" // (T = 22)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 23)
|
||||||
|
"ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 24)
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 26)
|
||||||
|
"sbiw %[count], 1" "\n\t" // 2 i-- (T = 28)
|
||||||
|
"brne head30" "\n" // 1-2 if(i != 0) -> (next byte)
|
||||||
|
: [port] "+e" (port),
|
||||||
|
[byte] "+r" (b),
|
||||||
|
[bit] "+r" (bit),
|
||||||
|
[next] "+r" (next),
|
||||||
|
[count] "+w" (i)
|
||||||
|
: [hi] "r" (hi),
|
||||||
|
[lo] "r" (lo),
|
||||||
|
[ptr] "e" (ptr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 16 MHz(ish) AVR --------------------------------------------------------
|
||||||
|
#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// WS2811 and WS2812 have different hi/lo duty cycles; this is
|
||||||
|
// similar but NOT an exact copy of the prior 400-on-8 code.
|
||||||
|
|
||||||
|
// 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL
|
||||||
|
// ST instructions: ^ ^ ^ (T=0,5,13)
|
||||||
|
|
||||||
|
volatile uint8_t next, bit;
|
||||||
|
|
||||||
|
hi = *port | pinMask;
|
||||||
|
lo = *port & ~pinMask;
|
||||||
|
next = lo;
|
||||||
|
bit = 8;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"head20:" "\n\t" // Clk Pseudocode (T = 0)
|
||||||
|
"st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
|
||||||
|
"sbrc %[byte], 7" "\n\t" // 1-2 if(b & 128)
|
||||||
|
"mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
|
||||||
|
"dec %[bit]" "\n\t" // 1 bit-- (T = 5)
|
||||||
|
"st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 7)
|
||||||
|
"mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8)
|
||||||
|
"breq nextbyte20" "\n\t" // 1-2 if(bit == 0) (from dec above)
|
||||||
|
"rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 12)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 13)
|
||||||
|
"st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 16)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 18)
|
||||||
|
"rjmp head20" "\n\t" // 2 -> head20 (next bit out)
|
||||||
|
"nextbyte20:" "\n\t" // (T = 10)
|
||||||
|
"ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11)
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13)
|
||||||
|
"st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 16)
|
||||||
|
"sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
|
||||||
|
"brne head20" "\n" // 2 if(i != 0) -> (next byte)
|
||||||
|
: [port] "+e" (port),
|
||||||
|
[byte] "+r" (b),
|
||||||
|
[bit] "+r" (bit),
|
||||||
|
[next] "+r" (next),
|
||||||
|
[count] "+w" (i)
|
||||||
|
: [ptr] "e" (ptr),
|
||||||
|
[hi] "r" (hi),
|
||||||
|
[lo] "r" (lo));
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
} else { // 400 KHz
|
||||||
|
|
||||||
|
// The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version.
|
||||||
|
|
||||||
|
// 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL
|
||||||
|
// ST instructions: ^ ^ ^ (T=0,8,20)
|
||||||
|
|
||||||
|
volatile uint8_t next, bit;
|
||||||
|
|
||||||
|
hi = *port | pinMask;
|
||||||
|
lo = *port & ~pinMask;
|
||||||
|
next = lo;
|
||||||
|
bit = 8;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"head40:" "\n\t" // Clk Pseudocode (T = 0)
|
||||||
|
"st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
|
||||||
|
"sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
|
||||||
|
"mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 4)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 6)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 8)
|
||||||
|
"st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 10)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 12)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 14)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 16)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 18)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 20)
|
||||||
|
"st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 22)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 23)
|
||||||
|
"mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 24)
|
||||||
|
"dec %[bit]" "\n\t" // 1 bit-- (T = 25)
|
||||||
|
"breq nextbyte40" "\n\t" // 1-2 if(bit == 0)
|
||||||
|
"rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27)
|
||||||
|
"nop" "\n\t" // 1 nop (T = 28)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 30)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 32)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 34)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 36)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 38)
|
||||||
|
"rjmp head40" "\n\t" // 2 -> head40 (next bit out)
|
||||||
|
"nextbyte40:" "\n\t" // (T = 27)
|
||||||
|
"ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 28)
|
||||||
|
"ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 30)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 32)
|
||||||
|
"st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 34)
|
||||||
|
"rjmp .+0" "\n\t" // 2 nop nop (T = 36)
|
||||||
|
"sbiw %[count], 1" "\n\t" // 2 i-- (T = 38)
|
||||||
|
"brne head40" "\n" // 1-2 if(i != 0) -> (next byte)
|
||||||
|
: [port] "+e" (port),
|
||||||
|
[byte] "+r" (b),
|
||||||
|
[bit] "+r" (bit),
|
||||||
|
[next] "+r" (next),
|
||||||
|
[count] "+w" (i)
|
||||||
|
: [ptr] "e" (ptr),
|
||||||
|
[hi] "r" (hi),
|
||||||
|
[lo] "r" (lo));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "CPU SPEED NOT SUPPORTED"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__arm__)
|
||||||
|
|
||||||
|
#if defined(__MK20DX128__) || defined(__MK20DX256__) // Teensy 3.0 & 3.1
|
||||||
|
#define CYCLES_800_T0H (F_CPU / 2500000)
|
||||||
|
#define CYCLES_800_T1H (F_CPU / 1250000)
|
||||||
|
#define CYCLES_800 (F_CPU / 800000)
|
||||||
|
#define CYCLES_400_T0H (F_CPU / 2000000)
|
||||||
|
#define CYCLES_400_T1H (F_CPU / 833333)
|
||||||
|
#define CYCLES_400 (F_CPU / 400000)
|
||||||
|
|
||||||
|
uint8_t *p = pixels,
|
||||||
|
*end = p + numBytes, pix, mask;
|
||||||
|
volatile uint8_t *set = portSetRegister(pin),
|
||||||
|
*clr = portClearRegister(pin);
|
||||||
|
uint32_t cyc;
|
||||||
|
|
||||||
|
ARM_DEMCR |= ARM_DEMCR_TRCENA;
|
||||||
|
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
|
||||||
|
#endif
|
||||||
|
cyc = ARM_DWT_CYCCNT + CYCLES_800;
|
||||||
|
while(p < end) {
|
||||||
|
pix = *p++;
|
||||||
|
for(mask = 0x80; mask; mask >>= 1) {
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
|
||||||
|
cyc = ARM_DWT_CYCCNT;
|
||||||
|
*set = 1;
|
||||||
|
if(pix & mask) {
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H);
|
||||||
|
} else {
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H);
|
||||||
|
}
|
||||||
|
*clr = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
} else { // 400 kHz bitstream
|
||||||
|
cyc = ARM_DWT_CYCCNT + CYCLES_400;
|
||||||
|
while(p < end) {
|
||||||
|
pix = *p++;
|
||||||
|
for(mask = 0x80; mask; mask >>= 1) {
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
|
||||||
|
cyc = ARM_DWT_CYCCNT;
|
||||||
|
*set = 1;
|
||||||
|
if(pix & mask) {
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H);
|
||||||
|
} else {
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H);
|
||||||
|
}
|
||||||
|
*clr = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // Arduino Due
|
||||||
|
|
||||||
|
#define SCALE VARIANT_MCK / 2UL / 1000000UL
|
||||||
|
#define INST (2UL * F_CPU / VARIANT_MCK)
|
||||||
|
#define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST))
|
||||||
|
#define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST))
|
||||||
|
#define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST))
|
||||||
|
#define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST))
|
||||||
|
#define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST))
|
||||||
|
#define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST))
|
||||||
|
|
||||||
|
int pinMask, time0, time1, period, t;
|
||||||
|
Pio *port;
|
||||||
|
volatile WoReg *portSet, *portClear, *timeValue, *timeReset;
|
||||||
|
uint8_t *p, *end, pix, mask;
|
||||||
|
|
||||||
|
pmc_set_writeprotect(false);
|
||||||
|
pmc_enable_periph_clk((uint32_t)TC3_IRQn);
|
||||||
|
TC_Configure(TC1, 0,
|
||||||
|
TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1);
|
||||||
|
TC_Start(TC1, 0);
|
||||||
|
|
||||||
|
pinMask = g_APinDescription[pin].ulPin; // Don't 'optimize' these into
|
||||||
|
port = g_APinDescription[pin].pPort; // declarations above. Want to
|
||||||
|
portSet = &(port->PIO_SODR); // burn a few cycles after
|
||||||
|
portClear = &(port->PIO_CODR); // starting timer to minimize
|
||||||
|
timeValue = &(TC1->TC_CHANNEL[0].TC_CV); // the initial 'while'.
|
||||||
|
timeReset = &(TC1->TC_CHANNEL[0].TC_CCR);
|
||||||
|
p = pixels;
|
||||||
|
end = p + numBytes;
|
||||||
|
pix = *p++;
|
||||||
|
mask = 0x80;
|
||||||
|
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
|
||||||
|
#endif
|
||||||
|
time0 = TIME_800_0;
|
||||||
|
time1 = TIME_800_1;
|
||||||
|
period = PERIOD_800;
|
||||||
|
#ifdef NEO_KHZ400
|
||||||
|
} else { // 400 KHz bitstream
|
||||||
|
time0 = TIME_400_0;
|
||||||
|
time1 = TIME_400_1;
|
||||||
|
period = PERIOD_400;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(t = time0;; t = time0) {
|
||||||
|
if(pix & mask) t = time1;
|
||||||
|
while(*timeValue < period);
|
||||||
|
*portSet = pinMask;
|
||||||
|
*timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG;
|
||||||
|
while(*timeValue < t);
|
||||||
|
*portClear = pinMask;
|
||||||
|
if(!(mask >>= 1)) { // This 'inside-out' loop logic utilizes
|
||||||
|
if(p >= end) break; // idle time to minimize inter-byte delays.
|
||||||
|
pix = *p++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(*timeValue < period); // Wait for last bit
|
||||||
|
TC_Stop(TC1, 0);
|
||||||
|
|
||||||
|
#endif // end Arduino Due
|
||||||
|
|
||||||
|
#endif // end Architecture select
|
||||||
|
|
||||||
|
interrupts();
|
||||||
|
endTime = micros(); // Save EOD time for latch on next call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the output pin number
|
||||||
|
void Adafruit_NeoPixel::setPin(uint8_t p) {
|
||||||
|
pinMode(pin, INPUT);
|
||||||
|
pin = p;
|
||||||
|
pinMode(p, OUTPUT);
|
||||||
|
digitalWrite(p, LOW);
|
||||||
|
#ifdef __AVR__
|
||||||
|
port = portOutputRegister(digitalPinToPort(p));
|
||||||
|
pinMask = digitalPinToBitMask(p);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set pixel color from separate R,G,B components:
|
||||||
|
void Adafruit_NeoPixel::setPixelColor(
|
||||||
|
uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
if(n < numLEDs) {
|
||||||
|
if(brightness) { // See notes in setBrightness()
|
||||||
|
r = (r * brightness) >> 8;
|
||||||
|
g = (g * brightness) >> 8;
|
||||||
|
b = (b * brightness) >> 8;
|
||||||
|
}
|
||||||
|
uint8_t *p = &pixels[n * 3];
|
||||||
|
p[rOffset] = r;
|
||||||
|
p[gOffset] = g;
|
||||||
|
p[bOffset] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set pixel color from 'packed' 32-bit RGB color:
|
||||||
|
void Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
|
||||||
|
if(n < numLEDs) {
|
||||||
|
uint8_t
|
||||||
|
r = (uint8_t)(c >> 16),
|
||||||
|
g = (uint8_t)(c >> 8),
|
||||||
|
b = (uint8_t)c;
|
||||||
|
if(brightness) { // See notes in setBrightness()
|
||||||
|
r = (r * brightness) >> 8;
|
||||||
|
g = (g * brightness) >> 8;
|
||||||
|
b = (b * brightness) >> 8;
|
||||||
|
}
|
||||||
|
uint8_t *p = &pixels[n * 3];
|
||||||
|
p[rOffset] = r;
|
||||||
|
p[gOffset] = g;
|
||||||
|
p[bOffset] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert separate R,G,B into packed 32-bit RGB color.
|
||||||
|
// Packed format is always RGB, regardless of LED strand color order.
|
||||||
|
uint32_t Adafruit_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query color from previously-set pixel (returns packed 32-bit RGB value)
|
||||||
|
uint32_t Adafruit_NeoPixel::getPixelColor(uint16_t n) const {
|
||||||
|
if(n >= numLEDs) {
|
||||||
|
// Out of bounds, return no color.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t *p = &pixels[n * 3];
|
||||||
|
uint32_t c = ((uint32_t)p[rOffset] << 16) |
|
||||||
|
((uint32_t)p[gOffset] << 8) |
|
||||||
|
(uint32_t)p[bOffset];
|
||||||
|
// Adjust this back up to the true color, as setting a pixel color will
|
||||||
|
// scale it back down again.
|
||||||
|
if(brightness) { // See notes in setBrightness()
|
||||||
|
//Cast the color to a byte array
|
||||||
|
uint8_t * c_ptr =reinterpret_cast<uint8_t*>(&c);
|
||||||
|
c_ptr[0] = (c_ptr[0] << 8)/brightness;
|
||||||
|
c_ptr[1] = (c_ptr[1] << 8)/brightness;
|
||||||
|
c_ptr[2] = (c_ptr[2] << 8)/brightness;
|
||||||
|
}
|
||||||
|
return c; // Pixel # is out of bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns pointer to pixels[] array. Pixel data is stored in device-
|
||||||
|
// native format and is not translated here. Application will need to be
|
||||||
|
// aware whether pixels are RGB vs. GRB and handle colors appropriately.
|
||||||
|
uint8_t *Adafruit_NeoPixel::getPixels(void) const {
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Adafruit_NeoPixel::numPixels(void) const {
|
||||||
|
return numLEDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust output brightness; 0=darkest (off), 255=brightest. This does
|
||||||
|
// NOT immediately affect what's currently displayed on the LEDs. The
|
||||||
|
// next call to show() will refresh the LEDs at this level. However,
|
||||||
|
// this process is potentially "lossy," especially when increasing
|
||||||
|
// brightness. The tight timing in the WS2811/WS2812 code means there
|
||||||
|
// aren't enough free cycles to perform this scaling on the fly as data
|
||||||
|
// is issued. So we make a pass through the existing color data in RAM
|
||||||
|
// and scale it (subsequent graphics commands also work at this
|
||||||
|
// brightness level). If there's a significant step up in brightness,
|
||||||
|
// the limited number of steps (quantization) in the old data will be
|
||||||
|
// quite visible in the re-scaled version. For a non-destructive
|
||||||
|
// change, you'll need to re-render the full strip data. C'est la vie.
|
||||||
|
void Adafruit_NeoPixel::setBrightness(uint8_t b) {
|
||||||
|
// Stored brightness value is different than what's passed.
|
||||||
|
// This simplifies the actual scaling math later, allowing a fast
|
||||||
|
// 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t,
|
||||||
|
// adding 1 here may (intentionally) roll over...so 0 = max brightness
|
||||||
|
// (color values are interpreted literally; no scaling), 1 = min
|
||||||
|
// brightness (off), 255 = just below max brightness.
|
||||||
|
uint8_t newBrightness = b + 1;
|
||||||
|
if(newBrightness != brightness) { // Compare against prior value
|
||||||
|
// Brightness has changed -- re-scale existing data in RAM
|
||||||
|
uint8_t c,
|
||||||
|
*ptr = pixels,
|
||||||
|
oldBrightness = brightness - 1; // De-wrap old brightness value
|
||||||
|
uint16_t scale;
|
||||||
|
if(oldBrightness == 0) scale = 0; // Avoid /0
|
||||||
|
else if(b == 255) scale = 65535 / oldBrightness;
|
||||||
|
else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
|
||||||
|
for(uint16_t i=0; i<numBytes; i++) {
|
||||||
|
c = *ptr;
|
||||||
|
*ptr++ = (c * scale) >> 8;
|
||||||
|
}
|
||||||
|
brightness = newBrightness;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return the brightness value
|
||||||
|
uint8_t Adafruit_NeoPixel::getBrightness(void) const {
|
||||||
|
return brightness - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_NeoPixel::clear() {
|
||||||
|
memset(pixels, 0, numBytes);
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*--------------------------------------------------------------------
|
||||||
|
This file is part of the Adafruit NeoPixel library.
|
||||||
|
|
||||||
|
NeoPixel is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
NeoPixel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with NeoPixel. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef ADAFRUIT_NEOPIXEL_H
|
||||||
|
#define ADAFRUIT_NEOPIXEL_H
|
||||||
|
|
||||||
|
#if (ARDUINO >= 100)
|
||||||
|
#include <Arduino.h>
|
||||||
|
#else
|
||||||
|
#include <WProgram.h>
|
||||||
|
#include <pins_arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 'type' flags for LED pixels (third parameter to constructor):
|
||||||
|
#define NEO_RGB 0x00 // Wired for RGB data order
|
||||||
|
#define NEO_GRB 0x01 // Wired for GRB data order
|
||||||
|
#define NEO_BRG 0x04
|
||||||
|
|
||||||
|
#define NEO_COLMASK 0x01
|
||||||
|
#define NEO_KHZ800 0x02 // 800 KHz datastream
|
||||||
|
#define NEO_SPDMASK 0x02
|
||||||
|
// Trinket flash space is tight, v1 NeoPixels aren't handled by default.
|
||||||
|
// Remove the ifndef/endif to add support -- but code will be bigger.
|
||||||
|
// Conversely, can comment out the #defines to save space on other MCUs.
|
||||||
|
#ifndef __AVR_ATtiny85__
|
||||||
|
#define NEO_KHZ400 0x00 // 400 KHz datastream
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Adafruit_NeoPixel {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructor: number of LEDs, pin number, LED type
|
||||||
|
Adafruit_NeoPixel(uint16_t n, uint8_t p=6, uint8_t t=NEO_GRB + NEO_KHZ800);
|
||||||
|
~Adafruit_NeoPixel();
|
||||||
|
|
||||||
|
void
|
||||||
|
begin(void),
|
||||||
|
show(void),
|
||||||
|
setPin(uint8_t p),
|
||||||
|
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
|
||||||
|
setPixelColor(uint16_t n, uint32_t c),
|
||||||
|
setBrightness(uint8_t),
|
||||||
|
clear();
|
||||||
|
uint8_t
|
||||||
|
*getPixels(void) const,
|
||||||
|
getBrightness(void) const;
|
||||||
|
uint16_t
|
||||||
|
numPixels(void) const;
|
||||||
|
static uint32_t
|
||||||
|
Color(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
uint32_t
|
||||||
|
getPixelColor(uint16_t n) const;
|
||||||
|
inline bool
|
||||||
|
canShow(void) { return (micros() - endTime) >= 50L; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const uint16_t
|
||||||
|
numLEDs, // Number of RGB LEDs in strip
|
||||||
|
numBytes; // Size of 'pixels' buffer below
|
||||||
|
uint8_t
|
||||||
|
pin, // Output pin number
|
||||||
|
brightness,
|
||||||
|
*pixels, // Holds LED color values (3 bytes each)
|
||||||
|
rOffset, // Index of red byte within each 3-byte pixel
|
||||||
|
gOffset, // Index of green byte
|
||||||
|
bOffset; // Index of blue byte
|
||||||
|
const uint8_t
|
||||||
|
type; // Pixel flags (400 vs 800 KHz, RGB vs GRB color)
|
||||||
|
uint32_t
|
||||||
|
endTime; // Latch timing reference
|
||||||
|
#ifdef __AVR__
|
||||||
|
const volatile uint8_t
|
||||||
|
*port; // Output PORT register
|
||||||
|
uint8_t
|
||||||
|
pinMask; // Output PORT bitmask
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ADAFRUIT_NEOPIXEL_H
|
794
hardware/digistump/avr/libraries/Adafruit_NeoPixel/COPYING
Normal file
794
hardware/digistump/avr/libraries/Adafruit_NeoPixel/COPYING
Normal file
@ -0,0 +1,794 @@
|
|||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LGPL ADDENDUM:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
12
hardware/digistump/avr/libraries/Adafruit_NeoPixel/README.md
Normal file
12
hardware/digistump/avr/libraries/Adafruit_NeoPixel/README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Adafruit NeoPixel library
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Arduino library for controlling single-wire-based LED pixels and strip such as the [Adafruit 60 LED/meter Digital LED strip][strip], the [Adafruit FLORA RGB Smart Pixel][flora], the [Adafruit Breadboard-friendly RGB Smart Pixel][pixel], the [Adafruit NeoPixel Stick][stick], and the [Adafruit NeoPixel Shield][shield].
|
||||||
|
|
||||||
|
After downloading, rename folder to 'Adafruit_NeoPixel' and install in Arduino Libraries folder. Restart Arduino IDE, then open File->Sketchbook->Library->Adafruit_NeoPixel->strandtest sketch.
|
||||||
|
|
||||||
|
[flora]: http://adafruit.com/products/1060
|
||||||
|
[strip]: http://adafruit.com/products/1138
|
||||||
|
[pixel]: http://adafruit.com/products/1312
|
||||||
|
[stick]: http://adafruit.com/products/1426
|
||||||
|
[shield]: http://adafruit.com/products/1430
|
@ -0,0 +1,165 @@
|
|||||||
|
// This is a demonstration on how to use an input device to trigger changes on your neo pixels.
|
||||||
|
// You should wire a momentary push button to connect from ground to a digital IO pin. When you
|
||||||
|
// press the button it will change to a new pixel animation. Note that you need to press the
|
||||||
|
// button once to start the first animation!
|
||||||
|
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
#define BUTTON_PIN 2 // Digital IO pin connected to the button. This will be
|
||||||
|
// driven with a pull-up resistor so the switch should
|
||||||
|
// pull the pin to ground momentarily. On a high -> low
|
||||||
|
// transition the button press logic will execute.
|
||||||
|
|
||||||
|
#define PIXEL_PIN 6 // Digital IO pin connected to the NeoPixels.
|
||||||
|
|
||||||
|
#define PIXEL_COUNT 16
|
||||||
|
|
||||||
|
// Parameter 1 = number of pixels in strip, neopixel stick has 8
|
||||||
|
// Parameter 2 = pin number (most are valid)
|
||||||
|
// Parameter 3 = pixel type flags, add together as needed:
|
||||||
|
// NEO_RGB Pixels are wired for RGB bitstream
|
||||||
|
// NEO_GRB Pixels are wired for GRB bitstream, correct for neopixel stick
|
||||||
|
// NEO_KHZ400 400 KHz bitstream (e.g. FLORA pixels)
|
||||||
|
// NEO_KHZ800 800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
|
||||||
|
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
bool oldState = HIGH;
|
||||||
|
int showType = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
||||||
|
strip.begin();
|
||||||
|
strip.show(); // Initialize all pixels to 'off'
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Get current button state.
|
||||||
|
bool newState = digitalRead(BUTTON_PIN);
|
||||||
|
|
||||||
|
// Check if state changed from high to low (button press).
|
||||||
|
if (newState == LOW && oldState == HIGH) {
|
||||||
|
// Short delay to debounce button.
|
||||||
|
delay(20);
|
||||||
|
// Check if button is still low after debounce.
|
||||||
|
newState = digitalRead(BUTTON_PIN);
|
||||||
|
if (newState == LOW) {
|
||||||
|
showType++;
|
||||||
|
if (showType > 9)
|
||||||
|
showType=0;
|
||||||
|
startShow(showType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the last button state to the old state.
|
||||||
|
oldState = newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startShow(int i) {
|
||||||
|
switch(i){
|
||||||
|
case 0: colorWipe(strip.Color(0, 0, 0), 50); // Black/off
|
||||||
|
break;
|
||||||
|
case 1: colorWipe(strip.Color(255, 0, 0), 50); // Red
|
||||||
|
break;
|
||||||
|
case 2: colorWipe(strip.Color(0, 255, 0), 50); // Green
|
||||||
|
break;
|
||||||
|
case 3: colorWipe(strip.Color(0, 0, 255), 50); // Blue
|
||||||
|
break;
|
||||||
|
case 4: theaterChase(strip.Color(127, 127, 127), 50); // White
|
||||||
|
break;
|
||||||
|
case 5: theaterChase(strip.Color(127, 0, 0), 50); // Red
|
||||||
|
break;
|
||||||
|
case 6: theaterChase(strip.Color( 0, 0, 127), 50); // Blue
|
||||||
|
break;
|
||||||
|
case 7: rainbow(20);
|
||||||
|
break;
|
||||||
|
case 8: rainbowCycle(20);
|
||||||
|
break;
|
||||||
|
case 9: theaterChaseRainbow(50);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the dots one after the other with a color
|
||||||
|
void colorWipe(uint32_t c, uint8_t wait) {
|
||||||
|
for(uint16_t i=0; i<strip.numPixels(); i++) {
|
||||||
|
strip.setPixelColor(i, c);
|
||||||
|
strip.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rainbow(uint8_t wait) {
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
for(j=0; j<256; j++) {
|
||||||
|
for(i=0; i<strip.numPixels(); i++) {
|
||||||
|
strip.setPixelColor(i, Wheel((i+j) & 255));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
void rainbowCycle(uint8_t wait) {
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
|
||||||
|
for(i=0; i< strip.numPixels(); i++) {
|
||||||
|
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Theatre-style crawling lights.
|
||||||
|
void theaterChase(uint32_t c, uint8_t wait) {
|
||||||
|
for (int j=0; j<10; j++) { //do 10 cycles of chasing
|
||||||
|
for (int q=0; q < 3; q++) {
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, c); //turn every third pixel on
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
delay(wait);
|
||||||
|
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, 0); //turn every third pixel off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Theatre-style crawling lights with rainbow effect
|
||||||
|
void theaterChaseRainbow(uint8_t wait) {
|
||||||
|
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
|
||||||
|
for (int q=0; q < 3; q++) {
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
delay(wait);
|
||||||
|
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, 0); //turn every third pixel off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t Wheel(byte WheelPos) {
|
||||||
|
WheelPos = 255 - WheelPos;
|
||||||
|
if(WheelPos < 85) {
|
||||||
|
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
|
||||||
|
} else if(WheelPos < 170) {
|
||||||
|
WheelPos -= 85;
|
||||||
|
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
|
||||||
|
} else {
|
||||||
|
WheelPos -= 170;
|
||||||
|
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
|
||||||
|
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
// Which pin on the Arduino is connected to the NeoPixels?
|
||||||
|
#define PIN 1
|
||||||
|
|
||||||
|
// How many NeoPixels are attached to the Arduino?
|
||||||
|
#define NUMPIXELS 1
|
||||||
|
|
||||||
|
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
|
||||||
|
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
|
||||||
|
// example for more information on possible values.
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);
|
||||||
|
|
||||||
|
int delayval = 500; // delay for half a second
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pixels.begin(); // This initializes the NeoPixel library.
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.
|
||||||
|
for(int i=0;i<NUMPIXELS;i++){
|
||||||
|
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
|
||||||
|
pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.
|
||||||
|
pixels.show(); // This sends the updated pixel color to the hardware.
|
||||||
|
delay(delayval); // Delay for a period of time (in milliseconds).
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
|
||||||
|
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
// Which pin on the Arduino is connected to the NeoPixels?
|
||||||
|
#define PIN 6
|
||||||
|
|
||||||
|
// How many NeoPixels are attached to the Arduino?
|
||||||
|
#define NUMPIXELS 16
|
||||||
|
|
||||||
|
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
|
||||||
|
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
|
||||||
|
// example for more information on possible values.
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
int delayval = 500; // delay for half a second
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pixels.begin(); // This initializes the NeoPixel library.
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.
|
||||||
|
for(int i=0;i<NUMPIXELS;i++){
|
||||||
|
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
|
||||||
|
pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.
|
||||||
|
pixels.show(); // This sends the updated pixel color to the hardware.
|
||||||
|
delay(delayval); // Delay for a period of time (in milliseconds).
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
#define PIN 6
|
||||||
|
|
||||||
|
// Parameter 1 = number of pixels in strip
|
||||||
|
// Parameter 2 = Arduino pin number (most are valid)
|
||||||
|
// Parameter 3 = pixel type flags, add together as needed:
|
||||||
|
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
|
||||||
|
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
||||||
|
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
|
||||||
|
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
|
||||||
|
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
|
||||||
|
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
|
||||||
|
// and minimize distance between Arduino and first pixel. Avoid connecting
|
||||||
|
// on a live circuit...if you must, connect GND first.
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
strip.begin();
|
||||||
|
strip.show(); // Initialize all pixels to 'off'
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Some example procedures showing how to display to the pixels:
|
||||||
|
colorWipe(strip.Color(255, 0, 0), 50); // Red
|
||||||
|
colorWipe(strip.Color(0, 255, 0), 50); // Green
|
||||||
|
colorWipe(strip.Color(0, 0, 255), 50); // Blue
|
||||||
|
// Send a theater pixel chase in...
|
||||||
|
theaterChase(strip.Color(127, 127, 127), 50); // White
|
||||||
|
theaterChase(strip.Color(127, 0, 0), 50); // Red
|
||||||
|
theaterChase(strip.Color( 0, 0, 127), 50); // Blue
|
||||||
|
|
||||||
|
rainbow(20);
|
||||||
|
rainbowCycle(20);
|
||||||
|
theaterChaseRainbow(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the dots one after the other with a color
|
||||||
|
void colorWipe(uint32_t c, uint8_t wait) {
|
||||||
|
for(uint16_t i=0; i<strip.numPixels(); i++) {
|
||||||
|
strip.setPixelColor(i, c);
|
||||||
|
strip.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rainbow(uint8_t wait) {
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
for(j=0; j<256; j++) {
|
||||||
|
for(i=0; i<strip.numPixels(); i++) {
|
||||||
|
strip.setPixelColor(i, Wheel((i+j) & 255));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
void rainbowCycle(uint8_t wait) {
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
|
||||||
|
for(i=0; i< strip.numPixels(); i++) {
|
||||||
|
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Theatre-style crawling lights.
|
||||||
|
void theaterChase(uint32_t c, uint8_t wait) {
|
||||||
|
for (int j=0; j<10; j++) { //do 10 cycles of chasing
|
||||||
|
for (int q=0; q < 3; q++) {
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, c); //turn every third pixel on
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
delay(wait);
|
||||||
|
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, 0); //turn every third pixel off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Theatre-style crawling lights with rainbow effect
|
||||||
|
void theaterChaseRainbow(uint8_t wait) {
|
||||||
|
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
|
||||||
|
for (int q=0; q < 3; q++) {
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
delay(wait);
|
||||||
|
|
||||||
|
for (int i=0; i < strip.numPixels(); i=i+3) {
|
||||||
|
strip.setPixelColor(i+q, 0); //turn every third pixel off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t Wheel(byte WheelPos) {
|
||||||
|
WheelPos = 255 - WheelPos;
|
||||||
|
if(WheelPos < 85) {
|
||||||
|
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
|
||||||
|
} else if(WheelPos < 170) {
|
||||||
|
WheelPos -= 85;
|
||||||
|
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
|
||||||
|
} else {
|
||||||
|
WheelPos -= 170;
|
||||||
|
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For Adafruit_NeoPixel
|
||||||
|
#######################################
|
||||||
|
# Class
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
Adafruit_NeoPixel KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
setPixelColor KEYWORD2
|
||||||
|
setPin KEYWORD2
|
||||||
|
setBrightness KEYWORD2
|
||||||
|
numPixels KEYWORD2
|
||||||
|
getPixelColor KEYWORD2
|
||||||
|
Color KEYWORD2
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
NEO_GRB LITERAL1
|
||||||
|
NEO_COLMASK LITERAL1
|
||||||
|
NEO_KHZ800 LITERAL1
|
||||||
|
NEO_SPDMASK LITERAL1
|
||||||
|
NEO_RGB LITERAL1
|
||||||
|
NEO_KHZ400 LITERAL1
|
308
hardware/digistump/avr/libraries/DigiCDC/Changelog.txt
Normal file
308
hardware/digistump/avr/libraries/DigiCDC/Changelog.txt
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
This file documents changes in the firmware-only USB driver for atmel's AVR
|
||||||
|
microcontrollers. New entries are always appended to the end of the file.
|
||||||
|
Scroll down to the bottom to see the most recent changes.
|
||||||
|
|
||||||
|
2005-04-01:
|
||||||
|
- Implemented endpoint 1 as interrupt-in endpoint.
|
||||||
|
- Moved all configuration options to usbconfig.h which is not part of the
|
||||||
|
driver.
|
||||||
|
- Changed interface for usbVendorSetup().
|
||||||
|
- Fixed compatibility with ATMega8 device.
|
||||||
|
- Various minor optimizations.
|
||||||
|
|
||||||
|
2005-04-11:
|
||||||
|
- Changed interface to application: Use usbFunctionSetup(), usbFunctionRead()
|
||||||
|
and usbFunctionWrite() now. Added configuration options to choose which
|
||||||
|
of these functions to compile in.
|
||||||
|
- Assembler module delivers receive data non-inverted now.
|
||||||
|
- Made register and bit names compatible with more AVR devices.
|
||||||
|
|
||||||
|
2005-05-03:
|
||||||
|
- Allow address of usbRxBuf on any memory page as long as the buffer does
|
||||||
|
not cross 256 byte page boundaries.
|
||||||
|
- Better device compatibility: works with Mega88 now.
|
||||||
|
- Code optimization in debugging module.
|
||||||
|
- Documentation updates.
|
||||||
|
|
||||||
|
2006-01-02:
|
||||||
|
- Added (free) default Vendor- and Product-IDs bought from voti.nl.
|
||||||
|
- Added USBID-License.txt file which defines the rules for using the free
|
||||||
|
shared VID/PID pair.
|
||||||
|
- Added Readme.txt to the usbdrv directory which clarifies administrative
|
||||||
|
issues.
|
||||||
|
|
||||||
|
2006-01-25:
|
||||||
|
- Added "configured state" to become more standards compliant.
|
||||||
|
- Added "HALT" state for interrupt endpoint.
|
||||||
|
- Driver passes the "USB Command Verifier" test from usb.org now.
|
||||||
|
- Made "serial number" a configuration option.
|
||||||
|
- Minor optimizations, we now recommend compiler option "-Os" for best
|
||||||
|
results.
|
||||||
|
- Added a version number to usbdrv.h
|
||||||
|
|
||||||
|
2006-02-03:
|
||||||
|
- New configuration variable USB_BUFFER_SECTION for the memory section where
|
||||||
|
the USB rx buffer will go. This defaults to ".bss" if not defined. Since
|
||||||
|
this buffer MUST NOT cross 256 byte pages (not even touch a page at the
|
||||||
|
end), the user may want to pass a linker option similar to
|
||||||
|
"-Wl,--section-start=.mybuffer=0x800060".
|
||||||
|
- Provide structure for usbRequest_t.
|
||||||
|
- New defines for USB constants.
|
||||||
|
- Prepared for HID implementations.
|
||||||
|
- Increased data size limit for interrupt transfers to 8 bytes.
|
||||||
|
- New macro usbInterruptIsReady() to query interrupt buffer state.
|
||||||
|
|
||||||
|
2006-02-18:
|
||||||
|
- Ensure that the data token which is sent as an ack to an OUT transfer is
|
||||||
|
always zero sized. This fixes a bug where the host reports an error after
|
||||||
|
sending an out transfer to the device, although all data arrived at the
|
||||||
|
device.
|
||||||
|
- Updated docs in usbdrv.h to reflect changed API in usbFunctionWrite().
|
||||||
|
|
||||||
|
* Release 2006-02-20
|
||||||
|
|
||||||
|
- Give a compiler warning when compiling with debugging turned on.
|
||||||
|
- Added Oleg Semyonov's changes for IAR-cc compatibility.
|
||||||
|
- Added new (optional) functions usbDeviceConnect() and usbDeviceDisconnect()
|
||||||
|
(also thanks to Oleg!).
|
||||||
|
- Rearranged tests in usbPoll() to save a couple of instructions in the most
|
||||||
|
likely case that no actions are pending.
|
||||||
|
- We need a delay between the SET ADDRESS request until the new address
|
||||||
|
becomes active. This delay was handled in usbPoll() until now. Since the
|
||||||
|
spec says that the delay must not exceed 2ms, previous versions required
|
||||||
|
aggressive polling during the enumeration phase. We have now moved the
|
||||||
|
handling of the delay into the interrupt routine.
|
||||||
|
- We must not reply with NAK to a SETUP transaction. We can only achieve this
|
||||||
|
by making sure that the rx buffer is empty when SETUP tokens are expected.
|
||||||
|
We therefore don't pass zero sized data packets from the status phase of
|
||||||
|
a transfer to usbPoll(). This change MAY cause troubles if you rely on
|
||||||
|
receiving a less than 8 bytes long packet in usbFunctionWrite() to
|
||||||
|
identify the end of a transfer. usbFunctionWrite() will NEVER be called
|
||||||
|
with a zero length.
|
||||||
|
|
||||||
|
* Release 2006-03-14
|
||||||
|
|
||||||
|
- Improved IAR C support: tiny memory model, more devices
|
||||||
|
- Added template usbconfig.h file under the name usbconfig-prototype.h
|
||||||
|
|
||||||
|
* Release 2006-03-26
|
||||||
|
|
||||||
|
- Added provision for one more interrupt-in endpoint (endpoint 3).
|
||||||
|
- Added provision for one interrupt-out endpoint (endpoint 1).
|
||||||
|
- Added flowcontrol macros for USB.
|
||||||
|
- Added provision for custom configuration descriptor.
|
||||||
|
- Allow ANY two port bits for D+ and D-.
|
||||||
|
- Merged (optional) receive endpoint number into global usbRxToken variable.
|
||||||
|
- Use USB_CFG_IOPORTNAME instead of USB_CFG_IOPORT. We now construct the
|
||||||
|
variable name from the single port letter instead of computing the address
|
||||||
|
of related ports from the output-port address.
|
||||||
|
|
||||||
|
* Release 2006-06-26
|
||||||
|
|
||||||
|
- Updated documentation in usbdrv.h and usbconfig-prototype.h to reflect the
|
||||||
|
new features.
|
||||||
|
- Removed "#warning" directives because IAR does not understand them. Use
|
||||||
|
unused static variables instead to generate a warning.
|
||||||
|
- Do not include <avr/io.h> when compiling with IAR.
|
||||||
|
- Introduced USB_CFG_DESCR_PROPS_* in usbconfig.h to configure how each
|
||||||
|
USB descriptor should be handled. It is now possible to provide descriptor
|
||||||
|
data in Flash, RAM or dynamically at runtime.
|
||||||
|
- STALL is now a status in usbTxLen* instead of a message. We can now conform
|
||||||
|
to the spec and leave the stall status pending until it is cleared.
|
||||||
|
- Made usbTxPacketCnt1 and usbTxPacketCnt3 public. This allows the
|
||||||
|
application code to reset data toggling on interrupt pipes.
|
||||||
|
|
||||||
|
* Release 2006-07-18
|
||||||
|
|
||||||
|
- Added an #if !defined __ASSEMBLER__ to the warning in usbdrv.h. This fixes
|
||||||
|
an assembler error.
|
||||||
|
- usbDeviceDisconnect() takes pull-up resistor to high impedance now.
|
||||||
|
|
||||||
|
* Release 2007-02-01
|
||||||
|
|
||||||
|
- Merged in some code size improvements from usbtiny (thanks to Dick
|
||||||
|
Streefland for these optimizations!)
|
||||||
|
- Special alignment requirement for usbRxBuf not required any more. Thanks
|
||||||
|
again to Dick Streefland for this hint!
|
||||||
|
- Reverted to "#warning" instead of unused static variables -- new versions
|
||||||
|
of IAR CC should handle this directive.
|
||||||
|
- Changed Open Source license to GNU GPL v2 in order to make linking against
|
||||||
|
other free libraries easier. We no longer require publication of the
|
||||||
|
circuit diagrams, but we STRONGLY encourage it. If you improve the driver
|
||||||
|
itself, PLEASE grant us a royalty free license to your changes for our
|
||||||
|
commercial license.
|
||||||
|
|
||||||
|
* Release 2007-03-29
|
||||||
|
|
||||||
|
- New configuration option "USB_PUBLIC" in usbconfig.h.
|
||||||
|
- Set USB version number to 1.10 instead of 1.01.
|
||||||
|
- Code used USB_CFG_DESCR_PROPS_STRING_DEVICE and
|
||||||
|
USB_CFG_DESCR_PROPS_STRING_PRODUCT inconsistently. Changed all occurrences
|
||||||
|
to USB_CFG_DESCR_PROPS_STRING_PRODUCT.
|
||||||
|
- New assembler module for 16.5 MHz RC oscillator clock with PLL in receiver
|
||||||
|
code.
|
||||||
|
- New assembler module for 16 MHz crystal.
|
||||||
|
- usbdrvasm.S contains common code only, clock-specific parts have been moved
|
||||||
|
to usbdrvasm12.S, usbdrvasm16.S and usbdrvasm165.S respectively.
|
||||||
|
|
||||||
|
* Release 2007-06-25
|
||||||
|
|
||||||
|
- 16 MHz module: Do SE0 check in stuffed bits as well.
|
||||||
|
|
||||||
|
* Release 2007-07-07
|
||||||
|
|
||||||
|
- Define hi8(x) for IAR compiler to limit result to 8 bits. This is necessary
|
||||||
|
for negative values.
|
||||||
|
- Added 15 MHz module contributed by V. Bosch.
|
||||||
|
- Interrupt vector name can now be configured. This is useful if somebody
|
||||||
|
wants to use a different hardware interrupt than INT0.
|
||||||
|
|
||||||
|
* Release 2007-08-07
|
||||||
|
|
||||||
|
- Moved handleIn3 routine in usbdrvasm16.S so that relative jump range is
|
||||||
|
not exceeded.
|
||||||
|
- More config options: USB_RX_USER_HOOK(), USB_INITIAL_DATATOKEN,
|
||||||
|
USB_COUNT_SOF
|
||||||
|
- USB_INTR_PENDING can now be a memory address, not just I/O
|
||||||
|
|
||||||
|
* Release 2007-09-19
|
||||||
|
|
||||||
|
- Split out common parts of assembler modules into separate include file
|
||||||
|
- Made endpoint numbers configurable so that given interface definitions
|
||||||
|
can be matched. See USB_CFG_EP3_NUMBER in usbconfig-prototype.h.
|
||||||
|
- Store endpoint number for interrupt/bulk-out so that usbFunctionWriteOut()
|
||||||
|
can handle any number of endpoints.
|
||||||
|
- Define usbDeviceConnect() and usbDeviceDisconnect() even if no
|
||||||
|
USB_CFG_PULLUP_IOPORTNAME is defined. Directly set D+ and D- to 0 in this
|
||||||
|
case.
|
||||||
|
|
||||||
|
* Release 2007-12-01
|
||||||
|
|
||||||
|
- Optimize usbDeviceConnect() and usbDeviceDisconnect() for less code size
|
||||||
|
when USB_CFG_PULLUP_IOPORTNAME is not defined.
|
||||||
|
|
||||||
|
* Release 2007-12-13
|
||||||
|
|
||||||
|
- Renamed all include-only assembler modules from *.S to *.inc so that
|
||||||
|
people don't add them to their project sources.
|
||||||
|
- Distribute leap bits in tx loop more evenly for 16 MHz module.
|
||||||
|
- Use "macro" and "endm" instead of ".macro" and ".endm" for IAR
|
||||||
|
- Avoid compiler warnings for constant expr range by casting some values in
|
||||||
|
USB descriptors.
|
||||||
|
|
||||||
|
* Release 2008-01-21
|
||||||
|
|
||||||
|
- Fixed bug in 15 and 16 MHz module where the new address set with
|
||||||
|
SET_ADDRESS was already accepted at the next NAK or ACK we send, not at
|
||||||
|
the next data packet we send. This caused problems when the host polled
|
||||||
|
too fast. Thanks to Alexander Neumann for his help and patience debugging
|
||||||
|
this issue!
|
||||||
|
|
||||||
|
* Release 2008-02-05
|
||||||
|
|
||||||
|
- Fixed bug in 16.5 MHz module where a register was used in the interrupt
|
||||||
|
handler before it was pushed. This bug was introduced with version
|
||||||
|
2007-09-19 when common parts were moved to a separate file.
|
||||||
|
- Optimized CRC routine (thanks to Reimar Doeffinger).
|
||||||
|
|
||||||
|
* Release 2008-02-16
|
||||||
|
|
||||||
|
- Removed outdated IAR compatibility stuff (code sections).
|
||||||
|
- Added hook macros for USB_RESET_HOOK() and USB_SET_ADDRESS_HOOK().
|
||||||
|
- Added optional routine usbMeasureFrameLength() for calibration of the
|
||||||
|
internal RC oscillator.
|
||||||
|
|
||||||
|
* Release 2008-02-28
|
||||||
|
|
||||||
|
- USB_INITIAL_DATATOKEN defaults to USBPID_DATA1 now, which means that we
|
||||||
|
start with sending USBPID_DATA0.
|
||||||
|
- Changed defaults in usbconfig-prototype.h
|
||||||
|
- Added free USB VID/PID pair for MIDI class devices
|
||||||
|
- Restructured AVR-USB as separate package, not part of PowerSwitch any more.
|
||||||
|
|
||||||
|
* Release 2008-04-18
|
||||||
|
|
||||||
|
- Restructured usbdrv.c so that it is easier to read and understand.
|
||||||
|
- Better code optimization with gcc 4.
|
||||||
|
- If a second interrupt in endpoint is enabled, also add it to config
|
||||||
|
descriptor.
|
||||||
|
- Added config option for long transfers (above 254 bytes), see
|
||||||
|
USB_CFG_LONG_TRANSFERS in usbconfig.h.
|
||||||
|
- Added 20 MHz module contributed by Jeroen Benschop.
|
||||||
|
|
||||||
|
* Release 2008-05-13
|
||||||
|
|
||||||
|
- Fixed bug in libs-host/hiddata.c function usbhidGetReport(): length
|
||||||
|
was not incremented, pointer to length was incremented instead.
|
||||||
|
- Added code to command line tool(s) which claims an interface. This code
|
||||||
|
is disabled by default, but may be necessary on newer Linux kernels.
|
||||||
|
- Added usbconfig.h option "USB_CFG_CHECK_DATA_TOGGLING".
|
||||||
|
- New header "usbportability.h" prepares ports to other development
|
||||||
|
environments.
|
||||||
|
- Long transfers (above 254 bytes) did not work when usbFunctionRead() was
|
||||||
|
used to supply the data. Fixed this bug. [Thanks to Alexander Neumann!]
|
||||||
|
- In hiddata.c (example code for sending/receiving data over HID), use
|
||||||
|
USB_RECIP_DEVICE instead of USB_RECIP_INTERFACE for control transfers so
|
||||||
|
that we need not claim the interface.
|
||||||
|
- in usbPoll() loop 20 times polling for RESET state instead of 10 times.
|
||||||
|
This accounts for the higher clock rates we now support.
|
||||||
|
- Added a module for 12.8 MHz RC oscillator with PLL in receiver loop.
|
||||||
|
- Added hook to SOF code so that oscillator can be tuned to USB frame clock.
|
||||||
|
- Added timeout to waitForJ loop. Helps preventing unexpected hangs.
|
||||||
|
- Added example code for oscillator tuning to libs-device (thanks to
|
||||||
|
Henrik Haftmann for the idea to this routine).
|
||||||
|
- Implemented option USB_CFG_SUPPRESS_INTR_CODE.
|
||||||
|
|
||||||
|
* Release 2008-10-22
|
||||||
|
|
||||||
|
- Fixed libs-device/osctune.h: OSCCAL is memory address on ATMega88 and
|
||||||
|
similar, not offset of 0x20 needs to be added.
|
||||||
|
- Allow distribution under GPLv3 for those who have to link against other
|
||||||
|
code distributed under GPLv3.
|
||||||
|
|
||||||
|
* Release 2008-11-26
|
||||||
|
|
||||||
|
- Removed libusb-win32 dependency for hid-data example in Makefile.windows.
|
||||||
|
It was never required and confused many people.
|
||||||
|
- Added extern uchar usbRxToken to usbdrv.h.
|
||||||
|
- Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser.
|
||||||
|
|
||||||
|
* Release 2009-03-23
|
||||||
|
|
||||||
|
- Hid-mouse example used settings from hid-data example, fixed that.
|
||||||
|
- Renamed project to V-USB due to a trademark issue with Atmel(r).
|
||||||
|
- Changed CommercialLicense.txt and USBID-License.txt to make the
|
||||||
|
background of USB ID registration clearer.
|
||||||
|
|
||||||
|
* Release 2009-04-15
|
||||||
|
|
||||||
|
- Changed CommercialLicense.txt to reflect the new range of PIDs from
|
||||||
|
Jason Kotzin.
|
||||||
|
- Removed USBID-License.txt in favor of USB-IDs-for-free.txt and
|
||||||
|
USB-ID-FAQ.txt
|
||||||
|
- Fixed a bug in the 12.8 MHz module: End Of Packet decection was made in
|
||||||
|
the center between bit 0 and 1 of each byte. This is where the data lines
|
||||||
|
are expected to change and the sampled data may therefore be nonsense.
|
||||||
|
We therefore check EOP ONLY if bits 0 AND 1 have both been read as 0 on D-.
|
||||||
|
- Fixed a bitstuffing problem in the 16 MHz module: If bit 6 was stuffed,
|
||||||
|
the unstuffing code in the receiver routine was 1 cycle too long. If
|
||||||
|
multiple bytes had the unstuffing in bit 6, the error summed up until the
|
||||||
|
receiver was out of sync.
|
||||||
|
- Included option for faster CRC routine.
|
||||||
|
Thanks to Slawomir Fras (BoskiDialer) for this code!
|
||||||
|
- Updated bits in Configuration Descriptor's bmAttributes according to
|
||||||
|
USB 1.1 (in particular bit 7, it is a must-be-set bit now).
|
||||||
|
|
||||||
|
* Release 2009-08-22
|
||||||
|
|
||||||
|
- Moved first DBG1() after odDebugInit() in all examples.
|
||||||
|
- Use vector INT0_vect instead of SIG_INTERRUPT0 if defined. This makes
|
||||||
|
V-USB compatible with the new "p" suffix devices (e.g. ATMega328p).
|
||||||
|
- USB_CFG_CLOCK_KHZ setting is now required in usbconfig.h (no default any
|
||||||
|
more).
|
||||||
|
- New option USB_CFG_DRIVER_FLASH_PAGE allows boot loaders on devices with
|
||||||
|
more than 64 kB flash.
|
||||||
|
- Built-in configuration descriptor allows custom definition for second
|
||||||
|
endpoint now.
|
||||||
|
|
||||||
|
* Release 2010-07-15
|
166
hardware/digistump/avr/libraries/DigiCDC/CommercialLicense.txt
Normal file
166
hardware/digistump/avr/libraries/DigiCDC/CommercialLicense.txt
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
V-USB Driver Software License Agreement
|
||||||
|
Version 2009-08-03
|
||||||
|
|
||||||
|
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
|
||||||
|
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
|
||||||
|
THE AMOUNT ACCORDING TO SECTION 4 ("PAYMENT") TO OBJECTIVE DEVELOPMENT.
|
||||||
|
|
||||||
|
|
||||||
|
1 DEFINITIONS
|
||||||
|
|
||||||
|
1.1 "OBJECTIVE DEVELOPMENT" shall mean OBJECTIVE DEVELOPMENT Software GmbH,
|
||||||
|
Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA.
|
||||||
|
|
||||||
|
1.2 "You" shall mean the Licensee.
|
||||||
|
|
||||||
|
1.3 "V-USB" shall mean all files included in the package distributed under
|
||||||
|
the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/)
|
||||||
|
unless otherwise noted. This includes the firmware-only USB device
|
||||||
|
implementation for Atmel AVR microcontrollers, some simple device examples
|
||||||
|
and host side software examples and libraries.
|
||||||
|
|
||||||
|
|
||||||
|
2 LICENSE GRANTS
|
||||||
|
|
||||||
|
2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source
|
||||||
|
code of V-USB.
|
||||||
|
|
||||||
|
2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the
|
||||||
|
non-exclusive right to use, copy and distribute V-USB with your hardware
|
||||||
|
product(s), restricted by the limitations in section 3 below.
|
||||||
|
|
||||||
|
2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify
|
||||||
|
the source code and your copy of V-USB according to your needs.
|
||||||
|
|
||||||
|
2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB
|
||||||
|
Product ID(s), sent to you in e-mail. These Product IDs are reserved
|
||||||
|
exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID
|
||||||
|
ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen
|
||||||
|
Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from
|
||||||
|
Jason Kotzin (Clay Logic, www.claylogic.com). Both owners of the Vendor IDs
|
||||||
|
have obtained these IDs from the USB Implementers Forum, Inc.
|
||||||
|
(www.usb.org). OBJECTIVE DEVELOPMENT disclaims all liability which might
|
||||||
|
arise from the assignment of USB IDs.
|
||||||
|
|
||||||
|
2.5 USB Certification. Although not part of this agreement, we want to make
|
||||||
|
it clear that you cannot become USB certified when you use V-USB or a USB
|
||||||
|
Product ID assigned by OBJECTIVE DEVELOPMENT. AVR microcontrollers don't
|
||||||
|
meet the electrical specifications required by the USB specification and
|
||||||
|
the USB Implementers Forum certifies only members who bought a Vendor ID of
|
||||||
|
their own.
|
||||||
|
|
||||||
|
|
||||||
|
3 LICENSE RESTRICTIONS
|
||||||
|
|
||||||
|
3.1 Number of Units. Only one of the following three definitions is
|
||||||
|
applicable. Which one is determined by the amount you pay to OBJECTIVE
|
||||||
|
DEVELOPMENT, see section 4 ("Payment") below.
|
||||||
|
|
||||||
|
Hobby License: You may use V-USB according to section 2 above in no more
|
||||||
|
than 5 hardware units. These units must not be sold for profit.
|
||||||
|
|
||||||
|
Entry Level License: You may use V-USB according to section 2 above in no
|
||||||
|
more than 150 hardware units.
|
||||||
|
|
||||||
|
Professional License: You may use V-USB according to section 2 above in
|
||||||
|
any number of hardware units, except for large scale production ("unlimited
|
||||||
|
fair use"). Quantities below 10,000 units are not considered large scale
|
||||||
|
production. If your reach quantities which are obviously large scale
|
||||||
|
production, you must pay a license fee of 0.10 EUR per unit for all units
|
||||||
|
above 10,000.
|
||||||
|
|
||||||
|
3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber
|
||||||
|
any copy of V-USB, or any of the rights granted herein.
|
||||||
|
|
||||||
|
3.3 Transfer. You may not transfer your rights under this Agreement to
|
||||||
|
another party without OBJECTIVE DEVELOPMENT's prior written consent. If
|
||||||
|
such consent is obtained, you may permanently transfer this License to
|
||||||
|
another party. The recipient of such transfer must agree to all terms and
|
||||||
|
conditions of this Agreement.
|
||||||
|
|
||||||
|
3.4 Reservation of Rights. OBJECTIVE DEVELOPMENT retains all rights not
|
||||||
|
expressly granted.
|
||||||
|
|
||||||
|
3.5 Non-Exclusive Rights. Your license rights under this Agreement are
|
||||||
|
non-exclusive.
|
||||||
|
|
||||||
|
3.6 Third Party Rights. This Agreement cannot grant you rights controlled
|
||||||
|
by third parties. In particular, you are not allowed to use the USB logo or
|
||||||
|
other trademarks owned by the USB Implementers Forum, Inc. without their
|
||||||
|
consent. Since such consent depends on USB certification, it should be
|
||||||
|
noted that V-USB will not pass certification because it does not
|
||||||
|
implement checksum verification and the microcontroller ports do not meet
|
||||||
|
the electrical specifications.
|
||||||
|
|
||||||
|
|
||||||
|
4 PAYMENT
|
||||||
|
|
||||||
|
The payment amount depends on the variation of this agreement (according to
|
||||||
|
section 3.1) into which you want to enter. Concrete prices are listed on
|
||||||
|
OBJECTIVE DEVELOPMENT's web site, usually at
|
||||||
|
http://www.obdev.at/vusb/license.html. You agree to pay the amount listed
|
||||||
|
there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor
|
||||||
|
or reseller.
|
||||||
|
|
||||||
|
|
||||||
|
5 COPYRIGHT AND OWNERSHIP
|
||||||
|
|
||||||
|
V-USB is protected by copyright laws and international copyright
|
||||||
|
treaties, as well as other intellectual property laws and treaties. V-USB
|
||||||
|
is licensed, not sold.
|
||||||
|
|
||||||
|
|
||||||
|
6 TERM AND TERMINATION
|
||||||
|
|
||||||
|
6.1 Term. This Agreement shall continue indefinitely. However, OBJECTIVE
|
||||||
|
DEVELOPMENT may terminate this Agreement and revoke the granted license and
|
||||||
|
USB-IDs if you fail to comply with any of its terms and conditions.
|
||||||
|
|
||||||
|
6.2 Survival of Terms. All provisions regarding secrecy, confidentiality
|
||||||
|
and limitation of liability shall survive termination of this agreement.
|
||||||
|
|
||||||
|
|
||||||
|
7 DISCLAIMER OF WARRANTY AND LIABILITY
|
||||||
|
|
||||||
|
LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||||
|
KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE
|
||||||
|
DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER
|
||||||
|
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
|
||||||
|
NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE
|
||||||
|
TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
|
||||||
|
RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO
|
||||||
|
STATE/JURISDICTION.
|
||||||
|
|
||||||
|
LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
|
||||||
|
IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY
|
||||||
|
SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
|
||||||
|
(INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
|
||||||
|
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY
|
||||||
|
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE
|
||||||
|
PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE
|
||||||
|
DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY
|
||||||
|
CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS
|
||||||
|
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB.
|
||||||
|
|
||||||
|
|
||||||
|
8 MISCELLANEOUS TERMS
|
||||||
|
|
||||||
|
8.1 Marketing. OBJECTIVE DEVELOPMENT has the right to mention for marketing
|
||||||
|
purposes that you entered into this agreement.
|
||||||
|
|
||||||
|
8.2 Entire Agreement. This document represents the entire agreement between
|
||||||
|
OBJECTIVE DEVELOPMENT and you. It may only be modified in writing signed by
|
||||||
|
an authorized representative of both, OBJECTIVE DEVELOPMENT and you.
|
||||||
|
|
||||||
|
8.3 Severability. In case a provision of these terms and conditions should
|
||||||
|
be or become partly or entirely invalid, ineffective, or not executable,
|
||||||
|
the validity of all other provisions shall not be affected.
|
||||||
|
|
||||||
|
8.4 Applicable Law. This agreement is governed by the laws of the Republic
|
||||||
|
of Austria.
|
||||||
|
|
||||||
|
8.5 Responsible Courts. The responsible courts in Vienna/Austria will have
|
||||||
|
exclusive jurisdiction regarding all disputes in connection with this
|
||||||
|
agreement.
|
||||||
|
|
380
hardware/digistump/avr/libraries/DigiCDC/DigiCDC.cpp
Normal file
380
hardware/digistump/avr/libraries/DigiCDC/DigiCDC.cpp
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
CDC Arduino Library by Ihsan Kehribar (kehribar.me)
|
||||||
|
and Digistump LLC (digistump.com)
|
||||||
|
- all changes made under the same license as V-USB
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DigiCDC.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
uchar sendEmptyFrame;
|
||||||
|
static uchar intr3Status; /* used to control interrupt endpoint transmissions */
|
||||||
|
|
||||||
|
|
||||||
|
DigiCDCDevice::DigiCDCDevice(void){}
|
||||||
|
|
||||||
|
|
||||||
|
void DigiCDCDevice::delay(long milli) {
|
||||||
|
unsigned long last = millis();
|
||||||
|
while (milli > 0) {
|
||||||
|
unsigned long now = millis();
|
||||||
|
milli -= now - last;
|
||||||
|
last = now;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigiCDCDevice::flush(){
|
||||||
|
cli();
|
||||||
|
RingBuffer_InitBuffer(&rxBuf,rxBuf_Data,sizeof(rxBuf_Data));
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigiCDCDevice::begin(){
|
||||||
|
|
||||||
|
usbBegin();
|
||||||
|
|
||||||
|
}
|
||||||
|
size_t DigiCDCDevice::write(uint8_t chr)
|
||||||
|
{
|
||||||
|
if(RingBuffer_IsFull(&txBuf))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RingBuffer_Insert(&txBuf,chr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DigiCDCDevice::available()
|
||||||
|
{
|
||||||
|
return RingBuffer_GetCount(&rxBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DigiCDCDevice::read()
|
||||||
|
{
|
||||||
|
if(RingBuffer_IsEmpty(&rxBuf))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return RingBuffer_Remove(&rxBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DigiCDCDevice::peek()
|
||||||
|
{
|
||||||
|
if(RingBuffer_IsEmpty(&rxBuf))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return RingBuffer_Peek(&rxBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DigiCDCDevice::task(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
usbPollWrapper();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigiCDCDevice::refresh(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
usbPollWrapper();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DigiCDCDevice::end(void)
|
||||||
|
{
|
||||||
|
// drive both USB pins low to disconnect
|
||||||
|
usbDeviceDisconnect();
|
||||||
|
cli();
|
||||||
|
RingBuffer_InitBuffer(&rxBuf,rxBuf_Data,sizeof(rxBuf_Data));
|
||||||
|
sei();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DigiCDCDevice::operator bool() {
|
||||||
|
usbPollWrapper();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void DigiCDCDevice::usbBegin()
|
||||||
|
{
|
||||||
|
cli();
|
||||||
|
|
||||||
|
PORTB &= ~(_BV(USB_CFG_DMINUS_BIT) | _BV(USB_CFG_DPLUS_BIT));
|
||||||
|
usbDeviceDisconnect();
|
||||||
|
_delay_ms(250);
|
||||||
|
usbDeviceConnect();
|
||||||
|
usbInit();
|
||||||
|
|
||||||
|
RingBuffer_InitBuffer(&txBuf,txBuf_Data,sizeof(txBuf_Data));
|
||||||
|
RingBuffer_InitBuffer(&rxBuf,rxBuf_Data,sizeof(rxBuf_Data));
|
||||||
|
|
||||||
|
intr3Status = 0;
|
||||||
|
sendEmptyFrame = 0;
|
||||||
|
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DigiCDCDevice::usbPollWrapper()
|
||||||
|
{
|
||||||
|
usbPoll();
|
||||||
|
while((!(RingBuffer_IsEmpty(&txBuf)))&&(index<9))
|
||||||
|
{
|
||||||
|
tmp[index++] = RingBuffer_Remove(&txBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(usbInterruptIsReady())
|
||||||
|
{
|
||||||
|
if(sendEmptyFrame)
|
||||||
|
{
|
||||||
|
usbSetInterrupt(tmp,0);
|
||||||
|
sendEmptyFrame = 0;
|
||||||
|
}
|
||||||
|
else if(index>0)
|
||||||
|
{
|
||||||
|
usbSetInterrupt(tmp,index);
|
||||||
|
usbEnableAllRequests();
|
||||||
|
sendEmptyFrame = 1;
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need to report rx and tx carrier after open attempt */
|
||||||
|
if(intr3Status != 0 && usbInterruptIsReady3()){
|
||||||
|
static uchar serialStateNotification[10] = {0xa1, 0x20, 0, 0, 0, 0, 2, 0, 3, 0};
|
||||||
|
|
||||||
|
if(intr3Status == 2){
|
||||||
|
usbSetInterrupt3(serialStateNotification, 8);
|
||||||
|
}else{
|
||||||
|
usbSetInterrupt3(serialStateNotification+8, 2);
|
||||||
|
}
|
||||||
|
intr3Status--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SEND_ENCAPSULATED_COMMAND = 0,
|
||||||
|
GET_ENCAPSULATED_RESPONSE,
|
||||||
|
SET_COMM_FEATURE,
|
||||||
|
GET_COMM_FEATURE,
|
||||||
|
CLEAR_COMM_FEATURE,
|
||||||
|
SET_LINE_CODING = 0x20,
|
||||||
|
GET_LINE_CODING,
|
||||||
|
SET_CONTROL_LINE_STATE,
|
||||||
|
SEND_BREAK
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PROGMEM char configDescrCDC[] = { /* USB configuration descriptor */
|
||||||
|
9, /* sizeof(usbDescrConfig): length of descriptor in bytes */
|
||||||
|
USBDESCR_CONFIG, /* descriptor type */
|
||||||
|
67,
|
||||||
|
0, /* total length of data returned (including inlined descriptors) */
|
||||||
|
2, /* number of interfaces in this configuration */
|
||||||
|
1, /* index of this configuration */
|
||||||
|
0, /* configuration name string index */
|
||||||
|
#if USB_CFG_IS_SELF_POWERED
|
||||||
|
(1 << 7) | USBATTR_SELFPOWER, /* attributes */
|
||||||
|
#else
|
||||||
|
(1 << 7), /* attributes */
|
||||||
|
#endif
|
||||||
|
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
|
||||||
|
|
||||||
|
/* interface descriptor follows inline: */
|
||||||
|
9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
|
||||||
|
USBDESCR_INTERFACE, /* descriptor type */
|
||||||
|
0, /* index of this interface */
|
||||||
|
0, /* alternate setting for this interface */
|
||||||
|
USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
|
||||||
|
USB_CFG_INTERFACE_CLASS,
|
||||||
|
USB_CFG_INTERFACE_SUBCLASS,
|
||||||
|
USB_CFG_INTERFACE_PROTOCOL,
|
||||||
|
0, /* string index for interface */
|
||||||
|
|
||||||
|
/* CDC Class-Specific descriptor */
|
||||||
|
5, /* sizeof(usbDescrCDC_HeaderFn): length of descriptor in bytes */
|
||||||
|
0x24, /* descriptor type */
|
||||||
|
0, /* header functional descriptor */
|
||||||
|
0x10, 0x01,
|
||||||
|
|
||||||
|
4, /* sizeof(usbDescrCDC_AcmFn): length of descriptor in bytes */
|
||||||
|
0x24, /* descriptor type */
|
||||||
|
2, /* abstract control management functional descriptor */
|
||||||
|
0x02, /* SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE */
|
||||||
|
|
||||||
|
5, /* sizeof(usbDescrCDC_UnionFn): length of descriptor in bytes */
|
||||||
|
0x24, /* descriptor type */
|
||||||
|
6, /* union functional descriptor */
|
||||||
|
0, /* CDC_COMM_INTF_ID */
|
||||||
|
1, /* CDC_DATA_INTF_ID */
|
||||||
|
|
||||||
|
5, /* sizeof(usbDescrCDC_CallMgtFn): length of descriptor in bytes */
|
||||||
|
0x24, /* descriptor type */
|
||||||
|
1, /* call management functional descriptor */
|
||||||
|
3, /* allow management on data interface, handles call management by itself */
|
||||||
|
1, /* CDC_DATA_INTF_ID */
|
||||||
|
|
||||||
|
/* Endpoint Descriptor */
|
||||||
|
7, /* sizeof(usbDescrEndpoint) */
|
||||||
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
||||||
|
0x80|USB_CFG_EP3_NUMBER, /* IN endpoint number 3 */
|
||||||
|
0x03, /* attrib: Interrupt endpoint */
|
||||||
|
8, 0, /* maximum packet size */
|
||||||
|
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
|
||||||
|
|
||||||
|
/* Interface Descriptor */
|
||||||
|
9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
|
||||||
|
USBDESCR_INTERFACE, /* descriptor type */
|
||||||
|
1, /* index of this interface */
|
||||||
|
0, /* alternate setting for this interface */
|
||||||
|
2, /* endpoints excl 0: number of endpoint descriptors to follow */
|
||||||
|
0x0A, /* Data Interface Class Codes */
|
||||||
|
0,
|
||||||
|
0, /* Data Interface Class Protocol Codes */
|
||||||
|
0, /* string index for interface */
|
||||||
|
|
||||||
|
/* Endpoint Descriptor */
|
||||||
|
7, /* sizeof(usbDescrEndpoint) */
|
||||||
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
||||||
|
0x01, /* OUT endpoint number 1 */
|
||||||
|
0x02, /* attrib: Bulk endpoint */
|
||||||
|
HW_CDC_BULK_OUT_SIZE, 0, /* maximum packet size */
|
||||||
|
0, /* in ms */
|
||||||
|
|
||||||
|
/* Endpoint Descriptor */
|
||||||
|
7, /* sizeof(usbDescrEndpoint) */
|
||||||
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
||||||
|
0x81, /* IN endpoint number 1 */
|
||||||
|
0x02, /* attrib: Bulk endpoint */
|
||||||
|
HW_CDC_BULK_IN_SIZE, 0, /* maximum packet size */
|
||||||
|
0, /* in ms */
|
||||||
|
};
|
||||||
|
|
||||||
|
uchar usbFunctionDescriptor(usbRequest_t *rq)
|
||||||
|
{
|
||||||
|
if(rq->wValue.bytes[1] == USBDESCR_DEVICE){
|
||||||
|
usbMsgPtr = (uchar *)usbDescriptorDevice;
|
||||||
|
return usbDescriptorDevice[0];
|
||||||
|
}else{ /* must be config descriptor */
|
||||||
|
usbMsgPtr = (uchar *)configDescrCDC;
|
||||||
|
return sizeof(configDescrCDC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* ----------------------------- USB interface ----------------------------- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
uchar usbFunctionSetup(uchar data[8])
|
||||||
|
{
|
||||||
|
usbRequest_t *rq = (usbRequest_t*)((void *)data);
|
||||||
|
|
||||||
|
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
|
||||||
|
|
||||||
|
if( rq->bRequest==GET_LINE_CODING || rq->bRequest==SET_LINE_CODING ){
|
||||||
|
return 0xff;
|
||||||
|
/* GET_LINE_CODING -> usbFunctionRead() */
|
||||||
|
/* SET_LINE_CODING -> usbFunctionWrite() */
|
||||||
|
}
|
||||||
|
if(rq->bRequest == SET_CONTROL_LINE_STATE){
|
||||||
|
/* Report serial state (carrier detect). On several Unix platforms,
|
||||||
|
* tty devices can only be opened when carrier detect is set.
|
||||||
|
*/
|
||||||
|
if( intr3Status==0 )
|
||||||
|
intr3Status = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare bulk-in endpoint to respond to early termination */
|
||||||
|
if((rq->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_HOST_TO_DEVICE)
|
||||||
|
sendEmptyFrame = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* usbFunctionRead */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uchar usbFunctionRead( uchar *data, uchar len )
|
||||||
|
{
|
||||||
|
// data[0] = 0;
|
||||||
|
// data[1] = 0;
|
||||||
|
// data[2] = 0;
|
||||||
|
// data[3] = 0;
|
||||||
|
// data[4] = 0;
|
||||||
|
// data[5] = 0;
|
||||||
|
// data[6] = 8;
|
||||||
|
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* usbFunctionWrite */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uchar usbFunctionWrite( uchar *data, uchar len )
|
||||||
|
{
|
||||||
|
// baud.bytes[0] = data[0];
|
||||||
|
// baud.bytes[1] = data[1];
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbFunctionWriteOut( uchar *data, uchar len )
|
||||||
|
{
|
||||||
|
uint8_t qw = 0;
|
||||||
|
for(qw=0;qw<len;qw++)
|
||||||
|
{
|
||||||
|
if(!RingBuffer_IsFull(&rxBuf))
|
||||||
|
{
|
||||||
|
RingBuffer_Insert(&rxBuf,data[qw]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* postpone receiving next data */
|
||||||
|
if(RingBuffer_GetCount(&rxBuf) >= HW_CDC_BULK_OUT_SIZE)
|
||||||
|
{
|
||||||
|
usbDisableAllRequests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DigiCDCDevice SerialUSB;
|
65
hardware/digistump/avr/libraries/DigiCDC/DigiCDC.h
Normal file
65
hardware/digistump/avr/libraries/DigiCDC/DigiCDC.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
CDC Arduino Library by Ihsan Kehribar (kehribar.me)
|
||||||
|
and Digistump LLC (digistump.com)
|
||||||
|
- all changes made under the same license as V-USB
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef __DigiCDC_h__
|
||||||
|
#define __DigiCDC_h__
|
||||||
|
#include "usbdrv.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "ringBuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define HW_CDC_TX_BUF_SIZE 32
|
||||||
|
#define HW_CDC_RX_BUF_SIZE 32
|
||||||
|
#define HW_CDC_BULK_OUT_SIZE 8
|
||||||
|
#define HW_CDC_BULK_IN_SIZE 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* library functions and variables start */
|
||||||
|
static uint8_t tmp[HW_CDC_BULK_IN_SIZE];
|
||||||
|
static uint8_t index = 0;
|
||||||
|
|
||||||
|
static RingBuffer_t rxBuf;
|
||||||
|
static uint8_t rxBuf_Data[HW_CDC_RX_BUF_SIZE];
|
||||||
|
|
||||||
|
static RingBuffer_t txBuf;
|
||||||
|
static uint8_t txBuf_Data[HW_CDC_TX_BUF_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
class DigiCDCDevice : public Stream {
|
||||||
|
public:
|
||||||
|
DigiCDCDevice();
|
||||||
|
void begin(), begin(unsigned long x);
|
||||||
|
void end();
|
||||||
|
void refresh();
|
||||||
|
void task();
|
||||||
|
void delay(long milli);
|
||||||
|
virtual int available(void);
|
||||||
|
virtual int peek(void);
|
||||||
|
virtual int read(void);
|
||||||
|
virtual void flush(void);
|
||||||
|
virtual size_t write(uint8_t);
|
||||||
|
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(long n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(int n) { return write((uint8_t)n); }
|
||||||
|
using Print::write;
|
||||||
|
operator bool();
|
||||||
|
private:
|
||||||
|
void usbBegin();
|
||||||
|
void usbPollWrapper();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern DigiCDCDevice SerialUSB;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __DigiCDC_h__
|
361
hardware/digistump/avr/libraries/DigiCDC/License.txt
Normal file
361
hardware/digistump/avr/libraries/DigiCDC/License.txt
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
OBJECTIVE DEVELOPMENT GmbH's V-USB driver software is distributed under the
|
||||||
|
terms and conditions of the GNU GPL version 2 or the GNU GPL version 3. It is
|
||||||
|
your choice whether you apply the terms of version 2 or version 3. The full
|
||||||
|
text of GPLv2 is included below. In addition to the requirements in the GPL,
|
||||||
|
we STRONGLY ENCOURAGE you to do the following:
|
||||||
|
|
||||||
|
(1) Publish your entire project on a web site and drop us a note with the URL.
|
||||||
|
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
|
||||||
|
|
||||||
|
(2) Adhere to minimum publication standards. Please include AT LEAST:
|
||||||
|
- a circuit diagram in PDF, PNG or GIF format
|
||||||
|
- full source code for the host software
|
||||||
|
- a Readme.txt file in ASCII format which describes the purpose of the
|
||||||
|
project and what can be found in which directories and which files
|
||||||
|
- a reference to http://www.obdev.at/vusb/
|
||||||
|
|
||||||
|
(3) If you improve the driver firmware itself, please give us a free license
|
||||||
|
to your modifications for our commercial license offerings.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
172
hardware/digistump/avr/libraries/DigiCDC/Readme.txt
Normal file
172
hardware/digistump/avr/libraries/DigiCDC/Readme.txt
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
This is the Readme file to Objective Development's firmware-only USB driver
|
||||||
|
for Atmel AVR microcontrollers. For more information please visit
|
||||||
|
http://www.obdev.at/vusb/
|
||||||
|
|
||||||
|
This directory contains the USB firmware only. Copy it as-is to your own
|
||||||
|
project and add all .c and .S files to your project (these files are marked
|
||||||
|
with an asterisk in the list below). Then copy usbconfig-prototype.h as
|
||||||
|
usbconfig.h to your project and edit it according to your configuration.
|
||||||
|
|
||||||
|
|
||||||
|
TECHNICAL DOCUMENTATION
|
||||||
|
=======================
|
||||||
|
The technical documentation (API) for the firmware driver is contained in the
|
||||||
|
file "usbdrv.h". Please read all of it carefully! Configuration options are
|
||||||
|
documented in "usbconfig-prototype.h".
|
||||||
|
|
||||||
|
The driver consists of the following files:
|
||||||
|
Readme.txt ............. The file you are currently reading.
|
||||||
|
Changelog.txt .......... Release notes for all versions of the driver.
|
||||||
|
usbdrv.h ............... Driver interface definitions and technical docs.
|
||||||
|
* usbdrv.c ............... High level language part of the driver. Link this
|
||||||
|
module to your code!
|
||||||
|
* usbdrvasm.S ............ Assembler part of the driver. This module is mostly
|
||||||
|
a stub and includes one of the usbdrvasm*.S files
|
||||||
|
depending on processor clock. Link this module to
|
||||||
|
your code!
|
||||||
|
usbdrvasm*.inc ......... Assembler routines for particular clock frequencies.
|
||||||
|
Included by usbdrvasm.S, don't link it directly!
|
||||||
|
asmcommon.inc .......... Common assembler routines. Included by
|
||||||
|
usbdrvasm*.inc, don't link it directly!
|
||||||
|
usbconfig-prototype.h .. Prototype for your own usbdrv.h file.
|
||||||
|
* oddebug.c .............. Debug functions. Only used when DEBUG_LEVEL is
|
||||||
|
defined to a value greater than 0. Link this module
|
||||||
|
to your code!
|
||||||
|
oddebug.h .............. Interface definitions of the debug module.
|
||||||
|
usbportability.h ....... Header with compiler-dependent stuff.
|
||||||
|
usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this
|
||||||
|
module instead of usbdrvasm.S when you assembler
|
||||||
|
with IAR's tools.
|
||||||
|
License.txt ............ Open Source license for this driver.
|
||||||
|
CommercialLicense.txt .. Optional commercial license for this driver.
|
||||||
|
USB-ID-FAQ.txt ......... General infos about USB Product- and Vendor-IDs.
|
||||||
|
USB-IDs-for-free.txt ... List and terms of use for free shared PIDs.
|
||||||
|
|
||||||
|
(*) ... These files should be linked to your project.
|
||||||
|
|
||||||
|
|
||||||
|
CPU CORE CLOCK FREQUENCY
|
||||||
|
========================
|
||||||
|
We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz,
|
||||||
|
16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The
|
||||||
|
actual clock rate must be configured in usbconfig.h.
|
||||||
|
|
||||||
|
12 MHz Clock
|
||||||
|
This is the traditional clock rate of V-USB because it's the lowest clock
|
||||||
|
rate where the timing constraints of the USB spec can be met.
|
||||||
|
|
||||||
|
15 MHz Clock
|
||||||
|
Similar to 12 MHz, but some NOPs inserted. On the other hand, the higher clock
|
||||||
|
rate allows for some loops which make the resulting code size somewhat smaller
|
||||||
|
than the 12 MHz version.
|
||||||
|
|
||||||
|
16 MHz Clock
|
||||||
|
This clock rate has been added for users of the Arduino board and other
|
||||||
|
ready-made boards which come with a fixed 16 MHz crystal. It's also an option
|
||||||
|
if you need the slightly higher clock rate for performance reasons. Since
|
||||||
|
16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
|
||||||
|
is somewhat tricky and has to insert a leap cycle every third byte.
|
||||||
|
|
||||||
|
12.8 MHz and 16.5 MHz Clock
|
||||||
|
The assembler modules for these clock rates differ from the other modules
|
||||||
|
because they have been built for an RC oscillator with only 1% precision. The
|
||||||
|
receiver code inserts leap cycles to compensate for clock deviations. 1% is
|
||||||
|
also the precision which can be achieved by calibrating the internal RC
|
||||||
|
oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL
|
||||||
|
oscillator can reach 16.5 MHz with the RC oscillator. This includes the very
|
||||||
|
popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost
|
||||||
|
all AVRs can reach 12.8 MHz, although this is outside the specified range.
|
||||||
|
|
||||||
|
See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for
|
||||||
|
code which calibrates the RC oscillator based on the USB frame clock.
|
||||||
|
|
||||||
|
18 MHz Clock
|
||||||
|
This module is closer to the USB specification because it performs an on the
|
||||||
|
fly CRC check for incoming packets. Packets with invalid checksum are
|
||||||
|
discarded as required by the spec. If you also implement checks for data
|
||||||
|
PID toggling on application level (see option USB_CFG_CHECK_DATA_TOGGLING
|
||||||
|
in usbconfig.h for more info), this ensures data integrity. Due to the CRC
|
||||||
|
tables and alignment requirements, this code is bigger than modules for other
|
||||||
|
clock rates. To activate this module, you must define USB_CFG_CHECK_CRC to 1
|
||||||
|
and USB_CFG_CLOCK_KHZ to 18000 in usbconfig.h.
|
||||||
|
|
||||||
|
20 MHz Clock
|
||||||
|
This module is for people who won't do it with less than the maximum. Since
|
||||||
|
20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
|
||||||
|
uses similar tricks as the 16 MHz module to insert leap cycles.
|
||||||
|
|
||||||
|
|
||||||
|
USB IDENTIFIERS
|
||||||
|
===============
|
||||||
|
Every USB device needs a vendor- and a product-identifier (VID and PID). VIDs
|
||||||
|
are obtained from usb.org for a price of 1,500 USD. Once you have a VID, you
|
||||||
|
can assign PIDs at will.
|
||||||
|
|
||||||
|
Since an entry level cost of 1,500 USD is too high for most small companies
|
||||||
|
and hobbyists, we provide some VID/PID pairs for free. See the file
|
||||||
|
USB-IDs-for-free.txt for details.
|
||||||
|
|
||||||
|
Objective Development also has some license offerings which include product
|
||||||
|
IDs. See http://www.obdev.at/vusb/ for details.
|
||||||
|
|
||||||
|
|
||||||
|
DEVELOPMENT SYSTEM
|
||||||
|
==================
|
||||||
|
This driver has been developed and optimized for the GNU compiler version 3
|
||||||
|
and 4. We recommend that you use the GNU compiler suite because it is freely
|
||||||
|
available. V-USB has also been ported to the IAR compiler and assembler. It
|
||||||
|
has been tested with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the
|
||||||
|
"small" and "tiny" memory model. Not every release is tested with IAR CC and
|
||||||
|
the driver may therefore fail to compile with IAR. Please note that gcc is
|
||||||
|
more efficient for usbdrv.c because this module has been deliberately
|
||||||
|
optimized for gcc.
|
||||||
|
|
||||||
|
Gcc version 3 produces smaller code than version 4 due to new optimizing
|
||||||
|
capabilities which don't always improve things on 8 bit CPUs. The code size
|
||||||
|
generated by gcc 4 can be reduced with the compiler options
|
||||||
|
-fno-move-loop-invariants, -fno-tree-scev-cprop and
|
||||||
|
-fno-inline-small-functions in addition to -Os. On devices with more than
|
||||||
|
8k of flash memory, we also recommend the linker option --relax (written as
|
||||||
|
-Wl,--relax for gcc) to convert absolute calls into relative where possible.
|
||||||
|
|
||||||
|
For more information about optimizing options see:
|
||||||
|
|
||||||
|
http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html
|
||||||
|
|
||||||
|
These optimizations are good for gcc 4.x. Version 3.x of gcc does not support
|
||||||
|
most of these options and produces good code anyway.
|
||||||
|
|
||||||
|
|
||||||
|
USING V-USB FOR FREE
|
||||||
|
====================
|
||||||
|
The AVR firmware driver is published under the GNU General Public License
|
||||||
|
Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is
|
||||||
|
your choice whether you apply the terms of version 2 or version 3.
|
||||||
|
|
||||||
|
If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the
|
||||||
|
following things IN ADDITION to the obligations from the GPL:
|
||||||
|
|
||||||
|
(1) Publish your entire project on a web site and drop us a note with the URL.
|
||||||
|
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
|
||||||
|
If you don't have a web site, you can publish the project in obdev's
|
||||||
|
documentation wiki at
|
||||||
|
http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects.
|
||||||
|
|
||||||
|
(2) Adhere to minimum publication standards. Please include AT LEAST:
|
||||||
|
- a circuit diagram in PDF, PNG or GIF format
|
||||||
|
- full source code for the host software
|
||||||
|
- a Readme.txt file in ASCII format which describes the purpose of the
|
||||||
|
project and what can be found in which directories and which files
|
||||||
|
- a reference to http://www.obdev.at/vusb/
|
||||||
|
|
||||||
|
(3) If you improve the driver firmware itself, please give us a free license
|
||||||
|
to your modifications for our commercial license offerings.
|
||||||
|
|
||||||
|
|
||||||
|
COMMERCIAL LICENSES FOR V-USB
|
||||||
|
=============================
|
||||||
|
If you don't want to publish your source code under the terms of the GPL,
|
||||||
|
you can simply pay money for V-USB. As an additional benefit you get
|
||||||
|
USB PIDs for free, reserved exclusively to you. See the file
|
||||||
|
"CommercialLicense.txt" for details.
|
||||||
|
|
188
hardware/digistump/avr/libraries/DigiCDC/asmcommon.inc
Normal file
188
hardware/digistump/avr/libraries/DigiCDC/asmcommon.inc
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/* Name: asmcommon.inc
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2007-11-05
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* Revision: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||||
|
* appropriate implementation!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This file contains assembler code which is shared among the USB driver
|
||||||
|
implementations for different CPU cocks. Since the code must be inserted
|
||||||
|
in the middle of the module, it's split out into this file and #included.
|
||||||
|
|
||||||
|
Jump destinations called from outside:
|
||||||
|
sofError: Called when no start sequence was found.
|
||||||
|
se0: Called when a package has been successfully received.
|
||||||
|
overflow: Called when receive buffer overflows.
|
||||||
|
doReturn: Called after sending data.
|
||||||
|
|
||||||
|
Outside jump destinations used by this module:
|
||||||
|
waitForJ: Called to receive an already arriving packet.
|
||||||
|
sendAckAndReti:
|
||||||
|
sendNakAndReti:
|
||||||
|
sendCntAndReti:
|
||||||
|
usbSendAndReti:
|
||||||
|
|
||||||
|
The following macros must be defined before this file is included:
|
||||||
|
.macro POP_STANDARD
|
||||||
|
.endm
|
||||||
|
.macro POP_RETI
|
||||||
|
.endm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define token x1
|
||||||
|
|
||||||
|
overflow:
|
||||||
|
ldi x2, 1<<USB_INTR_PENDING_BIT
|
||||||
|
USB_STORE_PENDING(x2) ; clear any pending interrupts
|
||||||
|
ignorePacket:
|
||||||
|
clr token
|
||||||
|
rjmp storeTokenAndReturn
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Processing of received packet (numbers in brackets are cycles after center of SE0)
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
;This is the only non-error exit point for the software receiver loop
|
||||||
|
;we don't check any CRCs here because there is no time left.
|
||||||
|
se0:
|
||||||
|
subi cnt, USB_BUFSIZE ;[5]
|
||||||
|
neg cnt ;[6]
|
||||||
|
sub YL, cnt ;[7]
|
||||||
|
sbci YH, 0 ;[8]
|
||||||
|
ldi x2, 1<<USB_INTR_PENDING_BIT ;[9]
|
||||||
|
USB_STORE_PENDING(x2) ;[10] clear pending intr and check flag later. SE0 should be over.
|
||||||
|
ld token, y ;[11]
|
||||||
|
cpi token, USBPID_DATA0 ;[13]
|
||||||
|
breq handleData ;[14]
|
||||||
|
cpi token, USBPID_DATA1 ;[15]
|
||||||
|
breq handleData ;[16]
|
||||||
|
lds shift, usbDeviceAddr;[17]
|
||||||
|
ldd x2, y+1 ;[19] ADDR and 1 bit endpoint number
|
||||||
|
lsl x2 ;[21] shift out 1 bit endpoint number
|
||||||
|
cpse x2, shift ;[22]
|
||||||
|
rjmp ignorePacket ;[23]
|
||||||
|
/* only compute endpoint number in x3 if required later */
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT
|
||||||
|
ldd x3, y+2 ;[24] endpoint number + crc
|
||||||
|
rol x3 ;[26] shift in LSB of endpoint
|
||||||
|
#endif
|
||||||
|
cpi token, USBPID_IN ;[27]
|
||||||
|
breq handleIn ;[28]
|
||||||
|
cpi token, USBPID_SETUP ;[29]
|
||||||
|
breq handleSetupOrOut ;[30]
|
||||||
|
cpi token, USBPID_OUT ;[31]
|
||||||
|
brne ignorePacket ;[32] must be ack, nak or whatever
|
||||||
|
; rjmp handleSetupOrOut ; fallthrough
|
||||||
|
|
||||||
|
;Setup and Out are followed by a data packet two bit times (16 cycles) after
|
||||||
|
;the end of SE0. The sync code allows up to 40 cycles delay from the start of
|
||||||
|
;the sync pattern until the first bit is sampled. That's a total of 56 cycles.
|
||||||
|
handleSetupOrOut: ;[32]
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for endpoint != 0, set usbCurrentTok to address */
|
||||||
|
andi x3, 0xf ;[32]
|
||||||
|
breq storeTokenAndReturn ;[33]
|
||||||
|
mov token, x3 ;[34] indicate that this is endpoint x OUT
|
||||||
|
#endif
|
||||||
|
storeTokenAndReturn:
|
||||||
|
sts usbCurrentTok, token;[35]
|
||||||
|
doReturn:
|
||||||
|
POP_STANDARD ;[37] 12...16 cycles
|
||||||
|
USB_LOAD_PENDING(YL) ;[49]
|
||||||
|
sbrc YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving
|
||||||
|
rjmp waitForJ ;[51] save the pops and pushes -- a new interrupt is already pending
|
||||||
|
sofError:
|
||||||
|
POP_RETI ;macro call
|
||||||
|
reti
|
||||||
|
|
||||||
|
handleData:
|
||||||
|
#if USB_CFG_CHECK_CRC
|
||||||
|
CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error
|
||||||
|
#endif
|
||||||
|
lds shift, usbCurrentTok;[18]
|
||||||
|
tst shift ;[20]
|
||||||
|
breq doReturn ;[21]
|
||||||
|
lds x2, usbRxLen ;[22]
|
||||||
|
tst x2 ;[24]
|
||||||
|
brne sendNakAndReti ;[25]
|
||||||
|
; 2006-03-11: The following two lines fix a problem where the device was not
|
||||||
|
; recognized if usbPoll() was called less frequently than once every 4 ms.
|
||||||
|
cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack
|
||||||
|
brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP
|
||||||
|
#if USB_CFG_CHECK_DATA_TOGGLING
|
||||||
|
sts usbCurrentDataToken, token ; store for checking by C code
|
||||||
|
#endif
|
||||||
|
sts usbRxLen, cnt ;[28] store received data, swap buffers
|
||||||
|
sts usbRxToken, shift ;[30]
|
||||||
|
lds x2, usbInputBufOffset;[32] swap buffers
|
||||||
|
ldi cnt, USB_BUFSIZE ;[34]
|
||||||
|
sub cnt, x2 ;[35]
|
||||||
|
sts usbInputBufOffset, cnt;[36] buffers now swapped
|
||||||
|
rjmp sendAckAndReti ;[38] 40 + 17 = 57 until SOP
|
||||||
|
|
||||||
|
handleIn:
|
||||||
|
;We don't send any data as long as the C code has not processed the current
|
||||||
|
;input data and potentially updated the output data. That's more efficient
|
||||||
|
;in terms of code size than clearing the tx buffers when a packet is received.
|
||||||
|
lds x1, usbRxLen ;[30]
|
||||||
|
cpi x1, 1 ;[32] negative values are flow control, 0 means "buffer free"
|
||||||
|
brge sendNakAndReti ;[33] unprocessed input packet?
|
||||||
|
ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT
|
||||||
|
andi x3, 0xf ;[35] x3 contains endpoint
|
||||||
|
#if USB_CFG_SUPPRESS_INTR_CODE
|
||||||
|
brne sendNakAndReti ;[36]
|
||||||
|
#else
|
||||||
|
brne handleIn1 ;[36]
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
lds cnt, usbTxLen ;[37]
|
||||||
|
sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set
|
||||||
|
rjmp sendCntAndReti ;[40] 42 + 16 = 58 until SOP
|
||||||
|
sts usbTxLen, x1 ;[41] x1 == USBPID_NAK from above
|
||||||
|
ldi YL, lo8(usbTxBuf) ;[43]
|
||||||
|
ldi YH, hi8(usbTxBuf) ;[44]
|
||||||
|
rjmp usbSendAndReti ;[45] 57 + 12 = 59 until SOP
|
||||||
|
|
||||||
|
; Comment about when to set usbTxLen to USBPID_NAK:
|
||||||
|
; We should set it back when we receive the ACK from the host. This would
|
||||||
|
; be simple to implement: One static variable which stores whether the last
|
||||||
|
; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the
|
||||||
|
; ACK. However, we set it back immediately when we send the package,
|
||||||
|
; assuming that no error occurs and the host sends an ACK. We save one byte
|
||||||
|
; RAM this way and avoid potential problems with endless retries. The rest of
|
||||||
|
; the driver assumes error-free transfers anyway.
|
||||||
|
|
||||||
|
#if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
|
||||||
|
handleIn1: ;[38]
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
|
||||||
|
cpi x3, USB_CFG_EP3_NUMBER;[38]
|
||||||
|
breq handleIn3 ;[39]
|
||||||
|
#endif
|
||||||
|
lds cnt, usbTxLen1 ;[40]
|
||||||
|
sbrc cnt, 4 ;[42] all handshake tokens have bit 4 set
|
||||||
|
rjmp sendCntAndReti ;[43] 47 + 16 = 63 until SOP
|
||||||
|
sts usbTxLen1, x1 ;[44] x1 == USBPID_NAK from above
|
||||||
|
ldi YL, lo8(usbTxBuf1) ;[46]
|
||||||
|
ldi YH, hi8(usbTxBuf1) ;[47]
|
||||||
|
rjmp usbSendAndReti ;[48] 50 + 12 = 62 until SOP
|
||||||
|
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
handleIn3:
|
||||||
|
lds cnt, usbTxLen3 ;[41]
|
||||||
|
sbrc cnt, 4 ;[43]
|
||||||
|
rjmp sendCntAndReti ;[44] 49 + 16 = 65 until SOP
|
||||||
|
sts usbTxLen3, x1 ;[45] x1 == USBPID_NAK from above
|
||||||
|
ldi YL, lo8(usbTxBuf3) ;[47]
|
||||||
|
ldi YH, hi8(usbTxBuf3) ;[48]
|
||||||
|
rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -0,0 +1,16 @@
|
|||||||
|
#include <DigiCDC.h>
|
||||||
|
void setup() {
|
||||||
|
// initialize the digital pin as an output.
|
||||||
|
SerialUSB.begin();
|
||||||
|
SerialUSB.println("CDC Test");
|
||||||
|
}
|
||||||
|
|
||||||
|
// the loop routine runs over and over again forever:
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
if (SerialUSB.available()) {
|
||||||
|
SerialUSB.write(SerialUSB.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialUSB.delay(10); // keep usb alive // can alos use SerialUSB.refresh();
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
This is the Readme file for the libs-device directory. This directory contains
|
||||||
|
code snippets which may be useful for USB device firmware.
|
||||||
|
|
||||||
|
|
||||||
|
WHAT IS INCLUDED IN THIS DIRECTORY?
|
||||||
|
===================================
|
||||||
|
|
||||||
|
osccal.c and osccal.h
|
||||||
|
This module contains a function which calibrates the AVR's built-in RC
|
||||||
|
oscillator based on the USB frame clock. See osccal.h for a documentation
|
||||||
|
of the API.
|
||||||
|
|
||||||
|
osctune.h
|
||||||
|
This header file contains a code snippet for usbconfig.h. With this code,
|
||||||
|
you can keep the AVR's internal RC oscillator in sync with the USB frame
|
||||||
|
clock. This is a continuous synchronization, not a single calibration at
|
||||||
|
USB reset as with osccal.c above. Please note that this code works only
|
||||||
|
if D- is wired to the interrupt, not D+.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH.
|
||||||
|
http://www.obdev.at/
|
50
hardware/digistump/avr/libraries/DigiCDC/oddebug.c
Normal file
50
hardware/digistump/avr/libraries/DigiCDC/oddebug.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* Name: oddebug.c
|
||||||
|
* Project: AVR library
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2005-01-16
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: oddebug.c 692 2008-11-07 15:07:40Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "oddebug.h"
|
||||||
|
|
||||||
|
#if DEBUG_LEVEL > 0
|
||||||
|
|
||||||
|
#warning "Never compile production devices with debugging enabled"
|
||||||
|
|
||||||
|
static void uartPutc(char c)
|
||||||
|
{
|
||||||
|
while(!(ODDBG_USR & (1 << ODDBG_UDRE))); /* wait for data register empty */
|
||||||
|
ODDBG_UDR = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar hexAscii(uchar h)
|
||||||
|
{
|
||||||
|
h &= 0xf;
|
||||||
|
if(h >= 10)
|
||||||
|
h += 'a' - (uchar)10 - '0';
|
||||||
|
h += '0';
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printHex(uchar c)
|
||||||
|
{
|
||||||
|
uartPutc(hexAscii(c >> 4));
|
||||||
|
uartPutc(hexAscii(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
void odDebug(uchar prefix, uchar *data, uchar len)
|
||||||
|
{
|
||||||
|
printHex(prefix);
|
||||||
|
uartPutc(':');
|
||||||
|
while(len--){
|
||||||
|
uartPutc(' ');
|
||||||
|
printHex(*data++);
|
||||||
|
}
|
||||||
|
uartPutc('\r');
|
||||||
|
uartPutc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
123
hardware/digistump/avr/libraries/DigiCDC/oddebug.h
Normal file
123
hardware/digistump/avr/libraries/DigiCDC/oddebug.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* Name: oddebug.h
|
||||||
|
* Project: AVR library
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2005-01-16
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: oddebug.h 692 2008-11-07 15:07:40Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __oddebug_h_included__
|
||||||
|
#define __oddebug_h_included__
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This module implements a function for debug logs on the serial line of the
|
||||||
|
AVR microcontroller. Debugging can be configured with the define
|
||||||
|
'DEBUG_LEVEL'. If this macro is not defined or defined to 0, all debugging
|
||||||
|
calls are no-ops. If it is 1, DBG1 logs will appear, but not DBG2. If it is
|
||||||
|
2, DBG1 and DBG2 logs will be printed.
|
||||||
|
|
||||||
|
A debug log consists of a label ('prefix') to indicate which debug log created
|
||||||
|
the output and a memory block to dump in hex ('data' and 'len').
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef F_CPU
|
||||||
|
# define F_CPU 12000000 /* 12 MHz */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* make sure we have the UART defines: */
|
||||||
|
#include "usbportability.h"
|
||||||
|
|
||||||
|
#ifndef uchar
|
||||||
|
# define uchar unsigned char
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */
|
||||||
|
# warning "Debugging disabled because device has no UART"
|
||||||
|
# undef DEBUG_LEVEL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEBUG_LEVEL
|
||||||
|
# define DEBUG_LEVEL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if DEBUG_LEVEL > 0
|
||||||
|
# define DBG1(prefix, data, len) odDebug(prefix, data, len)
|
||||||
|
#else
|
||||||
|
# define DBG1(prefix, data, len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG_LEVEL > 1
|
||||||
|
# define DBG2(prefix, data, len) odDebug(prefix, data, len)
|
||||||
|
#else
|
||||||
|
# define DBG2(prefix, data, len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if DEBUG_LEVEL > 0
|
||||||
|
extern void odDebug(uchar prefix, uchar *data, uchar len);
|
||||||
|
|
||||||
|
/* Try to find our control registers; ATMEL likes to rename these */
|
||||||
|
|
||||||
|
#if defined UBRR
|
||||||
|
# define ODDBG_UBRR UBRR
|
||||||
|
#elif defined UBRRL
|
||||||
|
# define ODDBG_UBRR UBRRL
|
||||||
|
#elif defined UBRR0
|
||||||
|
# define ODDBG_UBRR UBRR0
|
||||||
|
#elif defined UBRR0L
|
||||||
|
# define ODDBG_UBRR UBRR0L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined UCR
|
||||||
|
# define ODDBG_UCR UCR
|
||||||
|
#elif defined UCSRB
|
||||||
|
# define ODDBG_UCR UCSRB
|
||||||
|
#elif defined UCSR0B
|
||||||
|
# define ODDBG_UCR UCSR0B
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined TXEN
|
||||||
|
# define ODDBG_TXEN TXEN
|
||||||
|
#else
|
||||||
|
# define ODDBG_TXEN TXEN0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined USR
|
||||||
|
# define ODDBG_USR USR
|
||||||
|
#elif defined UCSRA
|
||||||
|
# define ODDBG_USR UCSRA
|
||||||
|
#elif defined UCSR0A
|
||||||
|
# define ODDBG_USR UCSR0A
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined UDRE
|
||||||
|
# define ODDBG_UDRE UDRE
|
||||||
|
#else
|
||||||
|
# define ODDBG_UDRE UDRE0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined UDR
|
||||||
|
# define ODDBG_UDR UDR
|
||||||
|
#elif defined UDR0
|
||||||
|
# define ODDBG_UDR UDR0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void odDebugInit(void)
|
||||||
|
{
|
||||||
|
ODDBG_UCR |= (1<<ODDBG_TXEN);
|
||||||
|
ODDBG_UBRR = F_CPU / (19200 * 16L) - 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define odDebugInit()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#endif /* __oddebug_h_included__ */
|
63
hardware/digistump/avr/libraries/DigiCDC/osccal.c
Normal file
63
hardware/digistump/avr/libraries/DigiCDC/osccal.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Name: osccal.c
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2008-04-10
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: osccal.c 762 2009-08-12 17:10:30Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
#ifndef uchar
|
||||||
|
#define uchar unsigned char
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* ------------------------ Oscillator Calibration ------------------------- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Calibrate the RC oscillator. Our timing reference is the Start Of Frame
|
||||||
|
* signal (a single SE0 bit) repeating every millisecond immediately after
|
||||||
|
* a USB RESET. We first do a binary search for the OSCCAL value and then
|
||||||
|
* optimize this value with a neighboorhod search.
|
||||||
|
*/
|
||||||
|
void calibrateOscillator(void)
|
||||||
|
{
|
||||||
|
uchar step = 128;
|
||||||
|
uchar trialValue = 0, optimumValue;
|
||||||
|
int x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
|
||||||
|
|
||||||
|
/* do a binary search: */
|
||||||
|
do{
|
||||||
|
OSCCAL = trialValue + step;
|
||||||
|
x = usbMeasureFrameLength(); /* proportional to current real frequency */
|
||||||
|
if(x < targetValue) /* frequency still too low */
|
||||||
|
trialValue += step;
|
||||||
|
step >>= 1;
|
||||||
|
}while(step > 0);
|
||||||
|
/* We have a precision of +/- 1 for optimum OSCCAL here */
|
||||||
|
/* now do a neighborhood search for optimum value */
|
||||||
|
optimumValue = trialValue;
|
||||||
|
optimumDev = x; /* this is certainly far away from optimum */
|
||||||
|
for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
|
||||||
|
x = usbMeasureFrameLength() - targetValue;
|
||||||
|
if(x < 0)
|
||||||
|
x = -x;
|
||||||
|
if(x < optimumDev){
|
||||||
|
optimumDev = x;
|
||||||
|
optimumValue = OSCCAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OSCCAL = optimumValue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Note: This calibration algorithm may try OSCCAL values of up to 192 even if
|
||||||
|
the optimum value is far below 192. It may therefore exceed the allowed clock
|
||||||
|
frequency of the CPU in low voltage designs!
|
||||||
|
You may replace this search algorithm with any other algorithm you like if
|
||||||
|
you have additional constraints such as a maximum CPU clock.
|
||||||
|
For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g.
|
||||||
|
ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in
|
||||||
|
both regions.
|
||||||
|
*/
|
65
hardware/digistump/avr/libraries/DigiCDC/osccal.h
Normal file
65
hardware/digistump/avr/libraries/DigiCDC/osccal.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* Name: osccal.h
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2008-04-10
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: osccal.h 762 2009-08-12 17:10:30Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This module contains a function which calibrates the AVR's internal RC
|
||||||
|
oscillator so that the CPU runs at F_CPU (F_CPU is a macro which must be
|
||||||
|
defined when the module is compiled, best passed in the compiler command
|
||||||
|
line). The time reference is the USB frame clock of 1 kHz available
|
||||||
|
immediately after a USB RESET condition. Timing is done by counting CPU
|
||||||
|
cycles, so all interrupts must be disabled while the calibration runs. For
|
||||||
|
low level timing measurements, usbMeasureFrameLength() is called. This
|
||||||
|
function must be enabled in usbconfig.h by defining
|
||||||
|
USB_CFG_HAVE_MEASURE_FRAME_LENGTH to 1. It is recommended to call
|
||||||
|
calibrateOscillator() from the reset hook in usbconfig.h:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
#include <avr/interrupt.h> // for sei()
|
||||||
|
extern void calibrateOscillator(void);
|
||||||
|
#endif
|
||||||
|
#define USB_RESET_HOOK(resetStarts) if(!resetStarts){cli(); calibrateOscillator(); sei();}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This routine is an alternative to the continuous synchronization described
|
||||||
|
in osctune.h.
|
||||||
|
|
||||||
|
Algorithm used:
|
||||||
|
calibrateOscillator() first does a binary search in the OSCCAL register for
|
||||||
|
the best matching oscillator frequency. Then it does a next neighbor search
|
||||||
|
to find the value with the lowest clock rate deviation. It is guaranteed to
|
||||||
|
find the best match among neighboring values, but for version 5 oscillators
|
||||||
|
(which have a discontinuous relationship between OSCCAL and frequency) a
|
||||||
|
better match might be available in another OSCCAL region.
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
This calibration algorithm may try OSCCAL values of up to 192 even if the
|
||||||
|
optimum value is far below 192. It may therefore exceed the allowed clock
|
||||||
|
frequency of the CPU in low voltage designs!
|
||||||
|
Precision depends on the OSCCAL vs. frequency dependency of the oscillator.
|
||||||
|
Typical precision for an ATMega168 (derived from the OSCCAL vs. F_RC diagram
|
||||||
|
in the data sheet) should be in the range of 0.4%. Only the 12.8 MHz and
|
||||||
|
16.5 MHz versions of V-USB (with built-in receiver PLL) can tolerate this
|
||||||
|
deviation! All other frequency modules require at least 0.2% precision.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __OSCCAL_H_INCLUDED__
|
||||||
|
#define __OSCCAL_H_INCLUDED__
|
||||||
|
|
||||||
|
//void calibrateOscillator(void);
|
||||||
|
/* This function calibrates the RC oscillator so that the CPU runs at F_CPU.
|
||||||
|
* It MUST be called immediately after the end of a USB RESET condition!
|
||||||
|
* Disable all interrupts during the call!
|
||||||
|
* It is recommended that you store the resulting value in EEPROM so that a
|
||||||
|
* good guess value is available after the next reset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __OSCCAL_H_INCLUDED__ */
|
88
hardware/digistump/avr/libraries/DigiCDC/osctune.h
Normal file
88
hardware/digistump/avr/libraries/DigiCDC/osctune.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* Name: osctune.h
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2008-10-18
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: osctune.h 692 2008-11-07 15:07:40Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This file is declared as C-header file although it is mostly documentation
|
||||||
|
how the RC oscillator can be kept in sync to the USB frame rate. The code
|
||||||
|
shown here must be added to usbconfig.h or this header file is included from
|
||||||
|
there. This code works only if D- is wired to the interrupt, not D+!!!
|
||||||
|
|
||||||
|
This is an alternative to the osccal routine in osccal.c. It has the advantage
|
||||||
|
that the synchronization is done continuously and that it has more compact
|
||||||
|
code size. The disadvantages are slow synchronization (it may take a while
|
||||||
|
until the driver works), that messages immediately after the SOF pulse may be
|
||||||
|
lost (and need to be retried by the host) and that the interrupt is on D-
|
||||||
|
contrary to most examples.
|
||||||
|
|
||||||
|
You may want to store a good calibration value in EEPROM for the next startup.
|
||||||
|
You know that the calibration value is good when the first USB message is
|
||||||
|
received. Do not store the value on every received message because the EEPROM
|
||||||
|
has a limited endurance.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
(*) You must declare the global character variable "lastTimer0Value" in your
|
||||||
|
main code.
|
||||||
|
|
||||||
|
(*) Timer 0 must be free running (not written by your code) and the prescaling
|
||||||
|
must be consistent with the TIMER0_PRESCALING define.
|
||||||
|
|
||||||
|
(*) Good values for Timer 0 prescaling depend on how precise the clock must
|
||||||
|
be tuned and how far away from the default clock rate the target clock is.
|
||||||
|
For precise tuning, choose a low prescaler factor, for a broad range of tuning
|
||||||
|
choose a high one. A prescaler factor of 64 is good for the entire OSCCAL
|
||||||
|
range and allows a precision of better than +/-1%. A prescaler factor of 8
|
||||||
|
allows tuning to slightly more than +/-6% of the default frequency and is
|
||||||
|
more precise than one step of OSCCAL. It is therefore not suitable to tune an
|
||||||
|
8 MHz oscillator to 12.5 MHz.
|
||||||
|
|
||||||
|
Thanks to Henrik Haftmann for the idea to this routine!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TIMER0_PRESCALING 64 /* must match the configuration for TIMER0 in main */
|
||||||
|
#define TOLERATED_DEVIATION_PPT 5 /* max clock deviation before we tune in 1/10 % */
|
||||||
|
/* derived constants: */
|
||||||
|
#define EXPECTED_TIMER0_INCREMENT ((F_CPU / (1000 * TIMER0_PRESCALING)) & 0xff)
|
||||||
|
#define TOLERATED_DEVIATION (TOLERATED_DEVIATION_PPT * F_CPU / (1000000 * TIMER0_PRESCALING))
|
||||||
|
|
||||||
|
#ifdef __ASSEMBLER__
|
||||||
|
macro tuneOsccal
|
||||||
|
push YH ;[0]
|
||||||
|
in YL, TCNT0 ;[2]
|
||||||
|
lds YH, lastTimer0Value ;[3]
|
||||||
|
sts lastTimer0Value, YL ;[5]
|
||||||
|
sub YL, YH ;[7] time passed since last frame
|
||||||
|
subi YL, EXPECTED_TIMER0_INCREMENT ;[8]
|
||||||
|
#if OSCCAL > 0x3f /* outside I/O addressable range */
|
||||||
|
lds YH, OSCCAL ;[6]
|
||||||
|
#else
|
||||||
|
in YH, OSCCAL ;[6] assembler modle uses __SFR_OFFSET == 0
|
||||||
|
#endif
|
||||||
|
cpi YL, TOLERATED_DEVIATION + 1 ;[10]
|
||||||
|
brmi notTooHigh ;[11]
|
||||||
|
subi YH, 1 ;[12] clock rate was too high
|
||||||
|
; brcs tuningOverflow ; optionally check for overflow
|
||||||
|
rjmp osctuneDone ;[13]
|
||||||
|
notTooHigh:
|
||||||
|
cpi YL, -TOLERATED_DEVIATION ;[13]
|
||||||
|
brpl osctuneDone ;[14] not too low
|
||||||
|
inc YH ;[15] clock rate was too low
|
||||||
|
; breq tuningOverflow ; optionally check for overflow
|
||||||
|
osctuneDone:
|
||||||
|
#if OSCCAL > 0x3f /* outside I/O addressable range */
|
||||||
|
sts OSCCAL, YH ;[12-13] store tuned value
|
||||||
|
#else
|
||||||
|
out OSCCAL, YH ;[12-13] store tuned value
|
||||||
|
#endif
|
||||||
|
tuningOverflow:
|
||||||
|
pop YH ;[17]
|
||||||
|
endm ;[19] max number of cycles
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_SOF_HOOK tuneOsccal
|
87
hardware/digistump/avr/libraries/DigiCDC/ringBuffer.h
Normal file
87
hardware/digistump/avr/libraries/DigiCDC/ringBuffer.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*******************************************************************************************************************
|
||||||
|
*
|
||||||
|
* See the http://www.fourwalledcubicle.com/files/LightweightRingBuff.h for the license information.
|
||||||
|
*
|
||||||
|
*******************************************************************************************************************/
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <util/atomic.h>
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t* In; /**< Current storage location in the circular buffer. */
|
||||||
|
uint8_t* Out; /**< Current retrieval location in the circular buffer. */
|
||||||
|
uint8_t* Start; /**< Pointer to the start of the buffer's underlying storage array. */
|
||||||
|
uint8_t* End; /**< Pointer to the end of the buffer's underlying storage array. */
|
||||||
|
uint16_t Size; /**< Size of the buffer's underlying storage array. */
|
||||||
|
uint16_t Count; /**< Number of bytes currently stored in the buffer. */
|
||||||
|
} RingBuffer_t;
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline void RingBuffer_InitBuffer(RingBuffer_t* Buffer,uint8_t* const DataPtr,const uint16_t Size)
|
||||||
|
{
|
||||||
|
Buffer->In = DataPtr;
|
||||||
|
Buffer->Out = DataPtr;
|
||||||
|
Buffer->Start = &DataPtr[0];
|
||||||
|
Buffer->End = &DataPtr[Size];
|
||||||
|
Buffer->Size = Size;
|
||||||
|
Buffer->Count = 0;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline uint16_t RingBuffer_GetCount(RingBuffer_t* const Buffer)
|
||||||
|
{
|
||||||
|
uint16_t Count;
|
||||||
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||||
|
{
|
||||||
|
Count = Buffer->Count;
|
||||||
|
}
|
||||||
|
return Count;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline uint16_t RingBuffer_GetFreeCount(RingBuffer_t* const Buffer)
|
||||||
|
{
|
||||||
|
return (Buffer->Size - RingBuffer_GetCount(Buffer));
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline uint8_t RingBuffer_IsEmpty(RingBuffer_t* const Buffer)
|
||||||
|
{
|
||||||
|
return (RingBuffer_GetCount(Buffer) == 0);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline uint8_t RingBuffer_IsFull(RingBuffer_t* const Buffer)
|
||||||
|
{
|
||||||
|
return (RingBuffer_GetCount(Buffer) == Buffer->Size);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline void RingBuffer_Insert(RingBuffer_t* Buffer, const uint8_t Data)
|
||||||
|
{
|
||||||
|
*Buffer->In = Data;
|
||||||
|
|
||||||
|
if (++Buffer->In == Buffer->End)
|
||||||
|
Buffer->In = Buffer->Start;
|
||||||
|
|
||||||
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||||
|
{
|
||||||
|
Buffer->Count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline uint8_t RingBuffer_Remove(RingBuffer_t* Buffer)
|
||||||
|
{
|
||||||
|
uint8_t Data = *Buffer->Out;
|
||||||
|
|
||||||
|
if (++Buffer->Out == Buffer->End)
|
||||||
|
Buffer->Out = Buffer->Start;
|
||||||
|
|
||||||
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||||
|
{
|
||||||
|
Buffer->Count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
||||||
|
static inline uint8_t RingBuffer_Peek(RingBuffer_t* const Buffer)
|
||||||
|
{
|
||||||
|
return *Buffer->Out;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------------------------------------------*/
|
376
hardware/digistump/avr/libraries/DigiCDC/usbconfig-prototype.h
Normal file
376
hardware/digistump/avr/libraries/DigiCDC/usbconfig-prototype.h
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
/* Name: usbconfig.h
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2005-04-01
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __usbconfig_h_included__
|
||||||
|
#define __usbconfig_h_included__
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This file is an example configuration (with inline documentation) for the USB
|
||||||
|
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
|
||||||
|
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
|
||||||
|
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
|
||||||
|
other hardware interrupt, as long as it is the highest level interrupt, see
|
||||||
|
section at the end of this file).
|
||||||
|
+ To create your own usbconfig.h file, copy this file to your project's
|
||||||
|
+ firmware source directory) and rename it to "usbconfig.h".
|
||||||
|
+ Then edit it accordingly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------- Hardware Config ---------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_IOPORTNAME D
|
||||||
|
/* This is the port where the USB bus is connected. When you configure it to
|
||||||
|
* "B", the registers PORTB, PINB and DDRB will be used.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DMINUS_BIT 4
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
|
||||||
|
* This may be any bit in the port.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DPLUS_BIT 2
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
|
||||||
|
* This may be any bit in the port. Please note that D+ must also be connected
|
||||||
|
* to interrupt pin INT0! [You can also use other interrupts, see section
|
||||||
|
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
|
||||||
|
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
|
||||||
|
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
|
||||||
|
* markers every millisecond.]
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
||||||
|
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
|
||||||
|
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code
|
||||||
|
* require no crystal, they tolerate +/- 1% deviation from the nominal
|
||||||
|
* frequency. All other rates require a precision of 2000 ppm and thus a
|
||||||
|
* crystal!
|
||||||
|
* Since F_CPU should be defined to your actual clock rate anyway, you should
|
||||||
|
* not need to modify this setting.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CHECK_CRC 0
|
||||||
|
/* Define this to 1 if you want that the driver checks integrity of incoming
|
||||||
|
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
|
||||||
|
* currently only available for 18 MHz crystal clock. You must choose
|
||||||
|
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Optional Hardware Config ------------------------ */
|
||||||
|
|
||||||
|
/* #define USB_CFG_PULLUP_IOPORTNAME D */
|
||||||
|
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
|
||||||
|
* V+, you can connect and disconnect the device from firmware by calling
|
||||||
|
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
|
||||||
|
* This constant defines the port on which the pullup resistor is connected.
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_PULLUP_BIT 4 */
|
||||||
|
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
|
||||||
|
* above) where the 1.5k pullup resistor is connected. See description
|
||||||
|
* above for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --------------------------- Functional Range ---------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT 0
|
||||||
|
/* Define this to 1 if you want to compile a version with two endpoints: The
|
||||||
|
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
|
||||||
|
* number).
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
|
||||||
|
/* Define this to 1 if you want to compile a version with three endpoints: The
|
||||||
|
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
|
||||||
|
* configured below) and a catch-all default interrupt-in endpoint as above.
|
||||||
|
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_EP3_NUMBER 3
|
||||||
|
/* If the so-called endpoint 3 is used, it can now be configured to any other
|
||||||
|
* endpoint number (except 0) with this macro. Default if undefined is 3.
|
||||||
|
*/
|
||||||
|
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
|
||||||
|
/* The above macro defines the startup condition for data toggling on the
|
||||||
|
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
|
||||||
|
* Since the token is toggled BEFORE sending any data, the first packet is
|
||||||
|
* sent with the oposite value of this configuration!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_HALT 0
|
||||||
|
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
|
||||||
|
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
|
||||||
|
* it is required by the standard. We have made it a config option because it
|
||||||
|
* bloats the code considerably.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_SUPPRESS_INTR_CODE 0
|
||||||
|
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
|
||||||
|
* want to send any data over them. If this macro is defined to 1, functions
|
||||||
|
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
|
||||||
|
* you need the interrupt-in endpoints in order to comply to an interface
|
||||||
|
* (e.g. HID), but never want to send any data. This option saves a couple
|
||||||
|
* of bytes in flash memory and the transmit buffers in RAM.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTR_POLL_INTERVAL 10
|
||||||
|
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
|
||||||
|
* interval. The value is in milliseconds and must not be less than 10 ms for
|
||||||
|
* low speed devices.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IS_SELF_POWERED 0
|
||||||
|
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
|
||||||
|
* device is powered from the USB bus.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_MAX_BUS_POWER 100
|
||||||
|
/* Set this variable to the maximum USB bus power consumption of your device.
|
||||||
|
* The value is in milliamperes. [It will be divided by two since USB
|
||||||
|
* communicates power requirements in units of 2 mA.]
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITE 0
|
||||||
|
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
|
||||||
|
* transfers. Set it to 0 if you don't need it and want to save a couple of
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_READ 0
|
||||||
|
/* Set this to 1 if you need to send control replies which are generated
|
||||||
|
* "on the fly" when usbFunctionRead() is called. If you only want to send
|
||||||
|
* data from a static buffer, set it to 0 and return the data from
|
||||||
|
* usbFunctionSetup(). This saves a couple of bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0
|
||||||
|
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
|
||||||
|
* You must implement the function usbFunctionWriteOut() which receives all
|
||||||
|
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
|
||||||
|
* can be found in 'usbRxToken'.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_FLOWCONTROL 0
|
||||||
|
/* Define this to 1 if you want flowcontrol over USB data. See the definition
|
||||||
|
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
|
||||||
|
* usbdrv.h.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DRIVER_FLASH_PAGE 0
|
||||||
|
/* If the device has more than 64 kBytes of flash, define this to the 64 k page
|
||||||
|
* where the driver's constants (descriptors) are located. Or in other words:
|
||||||
|
* Define this to 1 for boot loaders on the ATMega128.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_LONG_TRANSFERS 0
|
||||||
|
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
|
||||||
|
* in a single control-in or control-out transfer. Note that the capability
|
||||||
|
* for long transfers increases the driver size.
|
||||||
|
*/
|
||||||
|
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
|
||||||
|
/* This macro is a hook if you want to do unconventional things. If it is
|
||||||
|
* defined, it's inserted at the beginning of received message processing.
|
||||||
|
* If you eat the received message and don't want default processing to
|
||||||
|
* proceed, do a return after doing your things. One possible application
|
||||||
|
* (besides debugging) is to flash a status LED on each packet.
|
||||||
|
*/
|
||||||
|
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
|
||||||
|
/* This macro is a hook if you need to know when an USB RESET occurs. It has
|
||||||
|
* one parameter which distinguishes between the start of RESET state and its
|
||||||
|
* end.
|
||||||
|
*/
|
||||||
|
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
|
||||||
|
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
|
||||||
|
* received.
|
||||||
|
*/
|
||||||
|
#define USB_COUNT_SOF 0
|
||||||
|
/* define this macro to 1 if you need the global variable "usbSofCount" which
|
||||||
|
* counts SOF packets. This feature requires that the hardware interrupt is
|
||||||
|
* connected to D- instead of D+.
|
||||||
|
*/
|
||||||
|
/* #ifdef __ASSEMBLER__
|
||||||
|
* macro myAssemblerMacro
|
||||||
|
* in YL, TCNT0
|
||||||
|
* sts timer0Snapshot, YL
|
||||||
|
* endm
|
||||||
|
* #endif
|
||||||
|
* #define USB_SOF_HOOK myAssemblerMacro
|
||||||
|
* This macro (if defined) is executed in the assembler module when a
|
||||||
|
* Start Of Frame condition is detected. It is recommended to define it to
|
||||||
|
* the name of an assembler macro which is defined here as well so that more
|
||||||
|
* than one assembler instruction can be used. The macro may use the register
|
||||||
|
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
|
||||||
|
* immediately after an SOF pulse may be lost and must be retried by the host.
|
||||||
|
* What can you do with this hook? Since the SOF signal occurs exactly every
|
||||||
|
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
|
||||||
|
* designs running on the internal RC oscillator.
|
||||||
|
* Please note that Start Of Frame detection works only if D- is wired to the
|
||||||
|
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CHECK_DATA_TOGGLING 0
|
||||||
|
/* define this macro to 1 if you want to filter out duplicate data packets
|
||||||
|
* sent by the host. Duplicates occur only as a consequence of communication
|
||||||
|
* errors, when the host does not receive an ACK. Please note that you need to
|
||||||
|
* implement the filtering yourself in usbFunctionWriteOut() and
|
||||||
|
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
|
||||||
|
* for each control- and out-endpoint to check for duplicate packets.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
|
||||||
|
/* define this macro to 1 if you want the function usbMeasureFrameLength()
|
||||||
|
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
|
||||||
|
*/
|
||||||
|
#define USB_USE_FAST_CRC 0
|
||||||
|
/* The assembler module has two implementations for the CRC algorithm. One is
|
||||||
|
* faster, the other is smaller. This CRC routine is only used for transmitted
|
||||||
|
* messages where timing is not critical. The faster routine needs 31 cycles
|
||||||
|
* per byte while the smaller one needs 61 to 69 cycles. The faster routine
|
||||||
|
* may be worth the 32 bytes bigger code size if you transmit lots of data and
|
||||||
|
* run the AVR close to its limit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------- Device Description --------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
|
||||||
|
/* USB vendor ID for the device, low byte first. If you have registered your
|
||||||
|
* own Vendor ID, define it here. Otherwise you may use one of obdev's free
|
||||||
|
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x05dc = 1500 */
|
||||||
|
/* This is the ID of the product, low byte first. It is interpreted in the
|
||||||
|
* scope of the vendor ID. If you have registered your own VID with usb.org
|
||||||
|
* or if you have licensed a PID from somebody else, define it here. Otherwise
|
||||||
|
* you may use one of obdev's free shared VID/PID pairs. See the file
|
||||||
|
* USB-IDs-for-free.txt for details!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
|
||||||
|
/* Version number of the device: Minor number first, then major number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_VENDOR_NAME 'o', 'b', 'd', 'e', 'v', '.', 'a', 't'
|
||||||
|
#define USB_CFG_VENDOR_NAME_LEN 8
|
||||||
|
/* These two values define the vendor name returned by the USB device. The name
|
||||||
|
* must be given as a list of characters under single quotes. The characters
|
||||||
|
* are interpreted as Unicode (UTF-16) entities.
|
||||||
|
* If you don't want a vendor name string, undefine these macros.
|
||||||
|
* ALWAYS define a vendor name containing your Internet domain name if you use
|
||||||
|
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_NAME 'T', 'e', 'm', 'p', 'l', 'a', 't', 'e'
|
||||||
|
#define USB_CFG_DEVICE_NAME_LEN 8
|
||||||
|
/* Same as above for the device name. If you don't want a device name, undefine
|
||||||
|
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
|
||||||
|
* you use a shared VID/PID.
|
||||||
|
*/
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
|
||||||
|
/* Same as above for the serial number. If you don't want a serial number,
|
||||||
|
* undefine the macros.
|
||||||
|
* It may be useful to provide the serial number through other means than at
|
||||||
|
* compile time. See the section about descriptor properties below for how
|
||||||
|
* to fine tune control over USB descriptors such as the string descriptor
|
||||||
|
* for the serial number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_CLASS 0xff /* set to 0 if deferred to interface */
|
||||||
|
#define USB_CFG_DEVICE_SUBCLASS 0
|
||||||
|
/* See USB specification if you want to conform to an existing device class.
|
||||||
|
* Class 0xff is "vendor specific".
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTERFACE_CLASS 0 /* define class here if not at device level */
|
||||||
|
#define USB_CFG_INTERFACE_SUBCLASS 0
|
||||||
|
#define USB_CFG_INTERFACE_PROTOCOL 0
|
||||||
|
/* See USB specification if you want to conform to an existing device class or
|
||||||
|
* protocol. The following classes must be set at interface level:
|
||||||
|
* HID class is 3, no subclass and protocol required (but may be useful!)
|
||||||
|
* CDC class is 2, use subclass 2 and protocol 1 for ACM
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 42 */
|
||||||
|
/* Define this to the length of the HID report descriptor, if you implement
|
||||||
|
* an HID device. Otherwise don't define it or define it to 0.
|
||||||
|
* If you use this define, you must add a const PROGMEM character array named
|
||||||
|
* "usbHidReportDescriptor" to your code which contains the report descriptor.
|
||||||
|
* Don't forget to keep the array and this define in sync!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define USB_PUBLIC static */
|
||||||
|
/* Use the define above if you #include usbdrv.c instead of linking against it.
|
||||||
|
* This technique saves a couple of bytes in flash memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------- Fine Control over USB Descriptors ------------------- */
|
||||||
|
/* If you don't want to use the driver's default USB descriptors, you can
|
||||||
|
* provide our own. These can be provided as (1) fixed length static data in
|
||||||
|
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
|
||||||
|
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
|
||||||
|
* information about this function.
|
||||||
|
* Descriptor handling is configured through the descriptor's properties. If
|
||||||
|
* no properties are defined or if they are 0, the default descriptor is used.
|
||||||
|
* Possible properties are:
|
||||||
|
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
|
||||||
|
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
|
||||||
|
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
|
||||||
|
* you want RAM pointers.
|
||||||
|
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
|
||||||
|
* in static memory is in RAM, not in flash memory.
|
||||||
|
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
|
||||||
|
* the driver must know the descriptor's length. The descriptor itself is
|
||||||
|
* found at the address of a well known identifier (see below).
|
||||||
|
* List of static descriptor names (must be declared const PROGMEM if in flash):
|
||||||
|
* char usbDescriptorDevice[];
|
||||||
|
* char usbDescriptorConfiguration[];
|
||||||
|
* char usbDescriptorHidReport[];
|
||||||
|
* char usbDescriptorString0[];
|
||||||
|
* int usbDescriptorStringVendor[];
|
||||||
|
* int usbDescriptorStringDevice[];
|
||||||
|
* int usbDescriptorStringSerialNumber[];
|
||||||
|
* Other descriptors can't be provided statically, they must be provided
|
||||||
|
* dynamically at runtime.
|
||||||
|
*
|
||||||
|
* Descriptor properties are or-ed or added together, e.g.:
|
||||||
|
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
|
||||||
|
*
|
||||||
|
* The following descriptors are defined:
|
||||||
|
* USB_CFG_DESCR_PROPS_DEVICE
|
||||||
|
* USB_CFG_DESCR_PROPS_CONFIGURATION
|
||||||
|
* USB_CFG_DESCR_PROPS_STRINGS
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_0
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_VENDOR
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||||
|
* USB_CFG_DESCR_PROPS_HID
|
||||||
|
* USB_CFG_DESCR_PROPS_HID_REPORT
|
||||||
|
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
|
||||||
|
*
|
||||||
|
* Note about string descriptors: String descriptors are not just strings, they
|
||||||
|
* are Unicode strings prefixed with a 2 byte header. Example:
|
||||||
|
* int serialNumberDescriptor[] = {
|
||||||
|
* USB_STRING_DESCRIPTOR_HEADER(6),
|
||||||
|
* 'S', 'e', 'r', 'i', 'a', 'l'
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_CFG_DESCR_PROPS_DEVICE 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRINGS 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_0 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
|
||||||
|
|
||||||
|
/* ----------------------- Optional MCU Description ------------------------ */
|
||||||
|
|
||||||
|
/* The following configurations have working defaults in usbdrv.h. You
|
||||||
|
* usually don't need to set them explicitly. Only if you want to run
|
||||||
|
* the driver on a device which is not yet supported or with a compiler
|
||||||
|
* which is not fully supported (such as IAR C) or if you use a differnt
|
||||||
|
* interrupt than INT0, you may have to define some of these.
|
||||||
|
*/
|
||||||
|
/* #define USB_INTR_CFG MCUCR */
|
||||||
|
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
|
||||||
|
/* #define USB_INTR_CFG_CLR 0 */
|
||||||
|
/* #define USB_INTR_ENABLE GIMSK */
|
||||||
|
/* #define USB_INTR_ENABLE_BIT INT0 */
|
||||||
|
/* #define USB_INTR_PENDING GIFR */
|
||||||
|
/* #define USB_INTR_PENDING_BIT INTF0 */
|
||||||
|
/* #define USB_INTR_VECTOR INT0_vect */
|
||||||
|
|
||||||
|
#endif /* __usbconfig_h_included__ */
|
438
hardware/digistump/avr/libraries/DigiCDC/usbconfig.h
Normal file
438
hardware/digistump/avr/libraries/DigiCDC/usbconfig.h
Normal file
@ -0,0 +1,438 @@
|
|||||||
|
/* Name: usbconfig.h
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2005-04-01
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __usbconfig_h_included__
|
||||||
|
#define __usbconfig_h_included__
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This file is an example configuration (with inline documentation) for the USB
|
||||||
|
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
|
||||||
|
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
|
||||||
|
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
|
||||||
|
other hardware interrupt, as long as it is the highest level interrupt, see
|
||||||
|
section at the end of this file).
|
||||||
|
+ To create your own usbconfig.h file, copy this file to your project's
|
||||||
|
+ firmware source directory) and rename it to "usbconfig.h".
|
||||||
|
+ Then edit it accordingly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------- Hardware Config ---------------------------- */
|
||||||
|
|
||||||
|
/* #define USB_CFG_IOPORTNAME D */
|
||||||
|
/* This is the port where the USB bus is connected. When you configure it to
|
||||||
|
* "B", the registers PORTB, PINB and DDRB will be used.
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_DMINUS_BIT 4 */
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
|
||||||
|
* This may be any bit in the port.
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_DPLUS_BIT 2 */
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
|
||||||
|
* This may be any bit in the port. Please note that D+ must also be connected
|
||||||
|
* to interrupt pin INT0! [You can also use other interrupts, see section
|
||||||
|
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
|
||||||
|
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
|
||||||
|
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
|
||||||
|
* markers every millisecond.]
|
||||||
|
*/
|
||||||
|
#if defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny84__)
|
||||||
|
#define USB_CFG_IOPORTNAME B
|
||||||
|
#define USB_CFG_DMINUS_BIT 1
|
||||||
|
#define USB_CFG_DPLUS_BIT 2
|
||||||
|
|
||||||
|
#elif defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__)
|
||||||
|
#define USB_CFG_IOPORTNAME B
|
||||||
|
#define USB_CFG_DMINUS_BIT 3
|
||||||
|
#define USB_CFG_DPLUS_BIT 4
|
||||||
|
|
||||||
|
#elif defined (__AVR_ATtiny87__) || defined (__AVR_ATtiny167__)
|
||||||
|
#define USB_CFG_IOPORTNAME B
|
||||||
|
#define USB_CFG_DMINUS_BIT 3
|
||||||
|
#define USB_CFG_DPLUS_BIT 6
|
||||||
|
|
||||||
|
#elif defined (__AVR_ATtiny461__) || defined (__AVR_ATtiny861__)
|
||||||
|
#define USB_CFG_IOPORTNAME B
|
||||||
|
#define USB_CFG_DMINUS_BIT 5
|
||||||
|
#define USB_CFG_DPLUS_BIT 6
|
||||||
|
#else
|
||||||
|
/* ATtiny2313, ATmega8/48/88/168 */
|
||||||
|
#define USB_CFG_IOPORTNAME D
|
||||||
|
#define USB_CFG_DMINUS_BIT 3
|
||||||
|
#define USB_CFG_DPLUS_BIT 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
||||||
|
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
|
||||||
|
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code
|
||||||
|
* require no crystal, they tolerate +/- 1% deviation from the nominal
|
||||||
|
* frequency. All other rates require a precision of 2000 ppm and thus a
|
||||||
|
* crystal!
|
||||||
|
* Since F_CPU should be defined to your actual clock rate anyway, you should
|
||||||
|
* not need to modify this setting.
|
||||||
|
*/
|
||||||
|
#if USB_CFG_CLOCK_KHZ==18000
|
||||||
|
#define USB_CFG_CHECK_CRC 1
|
||||||
|
#else
|
||||||
|
#define USB_CFG_CHECK_CRC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define this to 1 if you want that the driver checks integrity of incoming
|
||||||
|
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
|
||||||
|
* currently only available for 18 MHz crystal clock. You must choose
|
||||||
|
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Optional Hardware Config ------------------------ */
|
||||||
|
|
||||||
|
/* #define USB_CFG_PULLUP_IOPORTNAME D */
|
||||||
|
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
|
||||||
|
* V+, you can connect and disconnect the device from firmware by calling
|
||||||
|
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
|
||||||
|
* This constant defines the port on which the pullup resistor is connected.
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_PULLUP_BIT 4 */
|
||||||
|
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
|
||||||
|
* above) where the 1.5k pullup resistor is connected. See description
|
||||||
|
* above for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --------------------------- Functional Range ---------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1
|
||||||
|
/* Define this to 1 if you want to compile a version with two endpoints: The
|
||||||
|
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
|
||||||
|
* number).
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1
|
||||||
|
/* Define this to 1 if you want to compile a version with three endpoints: The
|
||||||
|
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
|
||||||
|
* configured below) and a catch-all default interrupt-in endpoint as above.
|
||||||
|
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_EP3_NUMBER 3
|
||||||
|
/* If the so-called endpoint 3 is used, it can now be configured to any other
|
||||||
|
* endpoint number (except 0) with this macro. Default if undefined is 3.
|
||||||
|
*/
|
||||||
|
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
|
||||||
|
/* The above macro defines the startup condition for data toggling on the
|
||||||
|
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
|
||||||
|
* Since the token is toggled BEFORE sending any data, the first packet is
|
||||||
|
* sent with the oposite value of this configuration!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_HALT 0
|
||||||
|
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
|
||||||
|
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
|
||||||
|
* it is required by the standard. We have made it a config option because it
|
||||||
|
* bloats the code considerably.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_SUPPRESS_INTR_CODE 0
|
||||||
|
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
|
||||||
|
* want to send any data over them. If this macro is defined to 1, functions
|
||||||
|
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
|
||||||
|
* you need the interrupt-in endpoints in order to comply to an interface
|
||||||
|
* (e.g. HID), but never want to send any data. This option saves a couple
|
||||||
|
* of bytes in flash memory and the transmit buffers in RAM.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTR_POLL_INTERVAL 255
|
||||||
|
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
|
||||||
|
* interval. The value is in milliseconds and must not be less than 10 ms for
|
||||||
|
* low speed devices.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IS_SELF_POWERED 0
|
||||||
|
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
|
||||||
|
* device is powered from the USB bus.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_MAX_BUS_POWER 100
|
||||||
|
/* Set this variable to the maximum USB bus power consumption of your device.
|
||||||
|
* The value is in milliamperes. [It will be divided by two since USB
|
||||||
|
* communicates power requirements in units of 2 mA.]
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITE 1
|
||||||
|
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
|
||||||
|
* transfers. Set it to 0 if you don't need it and want to save a couple of
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_READ 1
|
||||||
|
/* Set this to 1 if you need to send control replies which are generated
|
||||||
|
* "on the fly" when usbFunctionRead() is called. If you only want to send
|
||||||
|
* data from a static buffer, set it to 0 and return the data from
|
||||||
|
* usbFunctionSetup(). This saves a couple of bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 1
|
||||||
|
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
|
||||||
|
* You must implement the function usbFunctionWriteOut() which receives all
|
||||||
|
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
|
||||||
|
* can be found in 'usbRxToken'.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_FLOWCONTROL 1
|
||||||
|
/* Define this to 1 if you want flowcontrol over USB data. See the definition
|
||||||
|
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
|
||||||
|
* usbdrv.h.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DRIVER_FLASH_PAGE 0
|
||||||
|
/* If the device has more than 64 kBytes of flash, define this to the 64 k page
|
||||||
|
* where the driver's constants (descriptors) are located. Or in other words:
|
||||||
|
* Define this to 1 for boot loaders on the ATMega128.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_LONG_TRANSFERS 0
|
||||||
|
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
|
||||||
|
* in a single control-in or control-out transfer. Note that the capability
|
||||||
|
* for long transfers increases the driver size.
|
||||||
|
*/
|
||||||
|
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
|
||||||
|
/* This macro is a hook if you want to do unconventional things. If it is
|
||||||
|
* defined, it's inserted at the beginning of received message processing.
|
||||||
|
* If you eat the received message and don't want default processing to
|
||||||
|
* proceed, do a return after doing your things. One possible application
|
||||||
|
* (besides debugging) is to flash a status LED on each packet.
|
||||||
|
*/
|
||||||
|
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
|
||||||
|
/* This macro is a hook if you need to know when an USB RESET occurs. It has
|
||||||
|
* one parameter which distinguishes between the start of RESET state and its
|
||||||
|
* end.
|
||||||
|
*/
|
||||||
|
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
|
||||||
|
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
|
||||||
|
* received.
|
||||||
|
*/
|
||||||
|
#define USB_COUNT_SOF 0
|
||||||
|
/* define this macro to 1 if you need the global variable "usbSofCount" which
|
||||||
|
* counts SOF packets. This feature requires that the hardware interrupt is
|
||||||
|
* connected to D- instead of D+.
|
||||||
|
*/
|
||||||
|
/* #ifdef __ASSEMBLER__
|
||||||
|
* macro myAssemblerMacro
|
||||||
|
* in YL, TCNT0
|
||||||
|
* sts timer0Snapshot, YL
|
||||||
|
* endm
|
||||||
|
* #endif
|
||||||
|
* #define USB_SOF_HOOK myAssemblerMacro
|
||||||
|
* This macro (if defined) is executed in the assembler module when a
|
||||||
|
* Start Of Frame condition is detected. It is recommended to define it to
|
||||||
|
* the name of an assembler macro which is defined here as well so that more
|
||||||
|
* than one assembler instruction can be used. The macro may use the register
|
||||||
|
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
|
||||||
|
* immediately after an SOF pulse may be lost and must be retried by the host.
|
||||||
|
* What can you do with this hook? Since the SOF signal occurs exactly every
|
||||||
|
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
|
||||||
|
* designs running on the internal RC oscillator.
|
||||||
|
* Please note that Start Of Frame detection works only if D- is wired to the
|
||||||
|
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CHECK_DATA_TOGGLING 0
|
||||||
|
/* define this macro to 1 if you want to filter out duplicate data packets
|
||||||
|
* sent by the host. Duplicates occur only as a consequence of communication
|
||||||
|
* errors, when the host does not receive an ACK. Please note that you need to
|
||||||
|
* implement the filtering yourself in usbFunctionWriteOut() and
|
||||||
|
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
|
||||||
|
* for each control- and out-endpoint to check for duplicate packets.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 1
|
||||||
|
#include "osccal.h"
|
||||||
|
|
||||||
|
/* define this macro to 1 if you want the function usbMeasureFrameLength()
|
||||||
|
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
|
||||||
|
*/
|
||||||
|
#define USB_USE_FAST_CRC 0
|
||||||
|
/* The assembler module has two implementations for the CRC algorithm. One is
|
||||||
|
* faster, the other is smaller. This CRC routine is only used for transmitted
|
||||||
|
* messages where timing is not critical. The faster routine needs 31 cycles
|
||||||
|
* per byte while the smaller one needs 61 to 69 cycles. The faster routine
|
||||||
|
* may be worth the 32 bytes bigger code size if you transmit lots of data and
|
||||||
|
* run the AVR close to its limit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------- Device Description --------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_VENDOR_ID 0xd0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
|
||||||
|
/* USB vendor ID for the device, low byte first. If you have registered your
|
||||||
|
* own Vendor ID, define it here. Otherwise you may use one of obdev's free
|
||||||
|
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_ID 0x7e, 0x08 /* = 0x05e1 = 1505 */
|
||||||
|
/* This is the ID of the product, low byte first. It is interpreted in the
|
||||||
|
* scope of the vendor ID. If you have registered your own VID with usb.org
|
||||||
|
* or if you have licensed a PID from somebody else, define it here. Otherwise
|
||||||
|
* you may use one of obdev's free shared VID/PID pairs. See the file
|
||||||
|
* USB-IDs-for-free.txt for details!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
|
||||||
|
/* Version number of the device: Minor number first, then major number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_VENDOR_NAME 'd','i','g','i','s','t','u','m','p','.','c','o','m'
|
||||||
|
#define USB_CFG_VENDOR_NAME_LEN 13
|
||||||
|
/* These two values define the vendor name returned by the USB device. The name
|
||||||
|
* must be given as a list of characters under single quotes. The characters
|
||||||
|
* are interpreted as Unicode (UTF-16) entities.
|
||||||
|
* If you don't want a vendor name string, undefine these macros.
|
||||||
|
* ALWAYS define a vendor name containing your Internet domain name if you use
|
||||||
|
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define USB_CFG_DEVICE_NAME 'D','i','g','i','s','p','a','r','k',' ','S','e','r','i','a','l'
|
||||||
|
#define USB_CFG_DEVICE_NAME_LEN 16
|
||||||
|
|
||||||
|
|
||||||
|
/* Same as above for the device name. If you don't want a device name, undefine
|
||||||
|
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
|
||||||
|
* you use a shared VID/PID.
|
||||||
|
*/
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
|
||||||
|
/* Same as above for the serial number. If you don't want a serial number,
|
||||||
|
* undefine the macros.
|
||||||
|
* It may be useful to provide the serial number through other means than at
|
||||||
|
* compile time. See the section about descriptor properties below for how
|
||||||
|
* to fine tune control over USB descriptors such as the string descriptor
|
||||||
|
* for the serial number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_CLASS 2 /* set to 0 if deferred to interface */
|
||||||
|
#define USB_CFG_DEVICE_SUBCLASS 0
|
||||||
|
/* See USB specification if you want to conform to an existing device class.
|
||||||
|
* Class 0xff is "vendor specific".
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTERFACE_CLASS 2 /* CDC class */
|
||||||
|
#define USB_CFG_INTERFACE_SUBCLASS 2 /* Abstract (Modem) */
|
||||||
|
#define USB_CFG_INTERFACE_PROTOCOL 1 /* AT-Commands */
|
||||||
|
/* See USB specification if you want to conform to an existing device class or
|
||||||
|
* protocol. The following classes must be set at interface level:
|
||||||
|
* HID class is 3, no subclass and protocol required (but may be useful!)
|
||||||
|
* CDC class is 2, use subclass 2 and protocol 1 for ACM
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 42 */
|
||||||
|
/* Define this to the length of the HID report descriptor, if you implement
|
||||||
|
* an HID device. Otherwise don't define it or define it to 0.
|
||||||
|
* If you use this define, you must add a const PROGMEM character array named
|
||||||
|
* "usbHidReportDescriptor" to your code which contains the report descriptor.
|
||||||
|
* Don't forget to keep the array and this define in sync!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define USB_PUBLIC static */
|
||||||
|
/* Use the define above if you #include usbdrv.c instead of linking against it.
|
||||||
|
* This technique saves a couple of bytes in flash memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------- Fine Control over USB Descriptors ------------------- */
|
||||||
|
/* If you don't want to use the driver's default USB descriptors, you can
|
||||||
|
* provide our own. These can be provided as (1) fixed length static data in
|
||||||
|
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
|
||||||
|
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
|
||||||
|
* information about this function.
|
||||||
|
* Descriptor handling is configured through the descriptor's properties. If
|
||||||
|
* no properties are defined or if they are 0, the default descriptor is used.
|
||||||
|
* Possible properties are:
|
||||||
|
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
|
||||||
|
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
|
||||||
|
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
|
||||||
|
* you want RAM pointers.
|
||||||
|
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
|
||||||
|
* in static memory is in RAM, not in flash memory.
|
||||||
|
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
|
||||||
|
* the driver must know the descriptor's length. The descriptor itself is
|
||||||
|
* found at the address of a well known identifier (see below).
|
||||||
|
* List of static descriptor names (must be declared const PROGMEM if in flash):
|
||||||
|
* char usbDescriptorDevice[];
|
||||||
|
* char usbDescriptorConfiguration[];
|
||||||
|
* char usbDescriptorHidReport[];
|
||||||
|
* char usbDescriptorString0[];
|
||||||
|
* int usbDescriptorStringVendor[];
|
||||||
|
* int usbDescriptorStringDevice[];
|
||||||
|
* int usbDescriptorStringSerialNumber[];
|
||||||
|
* Other descriptors can't be provided statically, they must be provided
|
||||||
|
* dynamically at runtime.
|
||||||
|
*
|
||||||
|
* Descriptor properties are or-ed or added together, e.g.:
|
||||||
|
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
|
||||||
|
*
|
||||||
|
* The following descriptors are defined:
|
||||||
|
* USB_CFG_DESCR_PROPS_DEVICE
|
||||||
|
* USB_CFG_DESCR_PROPS_CONFIGURATION
|
||||||
|
* USB_CFG_DESCR_PROPS_STRINGS
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_0
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_VENDOR
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||||
|
* USB_CFG_DESCR_PROPS_HID
|
||||||
|
* USB_CFG_DESCR_PROPS_HID_REPORT
|
||||||
|
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
|
||||||
|
*
|
||||||
|
* Note about string descriptors: String descriptors are not just strings, they
|
||||||
|
* are Unicode strings prefixed with a 2 byte header. Example:
|
||||||
|
* int serialNumberDescriptor[] = {
|
||||||
|
* USB_STRING_DESCRIPTOR_HEADER(6),
|
||||||
|
* 'S', 'e', 'r', 'i', 'a', 'l'
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_CFG_DESCR_PROPS_DEVICE 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRINGS 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_0 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
|
||||||
|
|
||||||
|
/* ----------------------- Optional MCU Description ------------------------ */
|
||||||
|
|
||||||
|
/* ATmega***p/pa needs SIG_ definitions */
|
||||||
|
#ifndef SIG_INTERRUPT0
|
||||||
|
#define SIG_INTERRUPT0 _VECTOR(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The following configurations have working defaults in usbdrv.h. You
|
||||||
|
* usually don't need to set them explicitly. Only if you want to run
|
||||||
|
* the driver on a device which is not yet supported or with a compiler
|
||||||
|
* which is not fully supported (such as IAR C) or if you use a differnt
|
||||||
|
* interrupt than INT0, you may have to define some of these.
|
||||||
|
*/
|
||||||
|
/* #define USB_INTR_CFG MCUCR */
|
||||||
|
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
|
||||||
|
/* #define USB_INTR_CFG_CLR 0 */
|
||||||
|
/* #define USB_INTR_ENABLE GIMSK */
|
||||||
|
/* #define USB_INTR_ENABLE_BIT INT0 */
|
||||||
|
/* #define USB_INTR_PENDING GIFR */
|
||||||
|
/* #define USB_INTR_PENDING_BIT INTF0 */
|
||||||
|
/* #define USB_INTR_VECTOR INT0_vect */
|
||||||
|
|
||||||
|
#if defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__)
|
||||||
|
#define USB_INTR_CFG PCMSK
|
||||||
|
#define USB_INTR_CFG_SET (1<<USB_CFG_DPLUS_BIT)
|
||||||
|
#define USB_INTR_ENABLE_BIT PCIE
|
||||||
|
#define USB_INTR_PENDING_BIT PCIF
|
||||||
|
#define USB_INTR_VECTOR SIG_PIN_CHANGE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (__AVR_ATtiny87__) || defined (__AVR_ATtiny167__)
|
||||||
|
#define USB_INTR_CFG PCMSK1
|
||||||
|
#define USB_INTR_CFG_SET (1 << USB_CFG_DPLUS_BIT)
|
||||||
|
#define USB_INTR_CFG_CLR 0
|
||||||
|
#define USB_INTR_ENABLE PCICR
|
||||||
|
#define USB_INTR_ENABLE_BIT PCIE1
|
||||||
|
#define USB_INTR_PENDING PCIFR
|
||||||
|
#define USB_INTR_PENDING_BIT PCIF1
|
||||||
|
#define USB_INTR_VECTOR PCINT1_vect
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __usbconfig_h_included__ */
|
625
hardware/digistump/avr/libraries/DigiCDC/usbdrv.c
Normal file
625
hardware/digistump/avr/libraries/DigiCDC/usbdrv.c
Normal file
@ -0,0 +1,625 @@
|
|||||||
|
/* Name: usbdrv.c
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2004-12-29
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: usbdrv.c 791 2010-07-15 15:56:13Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "usbportability.h"
|
||||||
|
#include "usbdrv.h"
|
||||||
|
#include "oddebug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This module implements the C-part of the USB driver. See usbdrv.h for a
|
||||||
|
documentation of the entire driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* raw USB registers / interface to assembler code: */
|
||||||
|
uchar usbRxBuf[2*USB_BUFSIZE]; /* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */
|
||||||
|
uchar usbInputBufOffset; /* offset in usbRxBuf used for low level receiving */
|
||||||
|
uchar usbDeviceAddr; /* assigned during enumeration, defaults to 0 */
|
||||||
|
uchar usbNewDeviceAddr; /* device ID which should be set after status phase */
|
||||||
|
uchar usbConfiguration; /* currently selected configuration. Administered by driver, but not used */
|
||||||
|
volatile schar usbRxLen; /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */
|
||||||
|
uchar usbCurrentTok; /* last token received or endpoint number for last OUT token if != 0 */
|
||||||
|
uchar usbRxToken; /* token for data we received; or endpont number for last OUT */
|
||||||
|
volatile uchar usbTxLen = USBPID_NAK; /* number of bytes to transmit with next IN token or handshake token */
|
||||||
|
uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */
|
||||||
|
#if USB_COUNT_SOF
|
||||||
|
volatile uchar usbSofCount; /* incremented by assembler module every SOF */
|
||||||
|
#endif
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
|
||||||
|
usbTxStatus_t usbTxStatus1;
|
||||||
|
# if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
usbTxStatus_t usbTxStatus3;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if USB_CFG_CHECK_DATA_TOGGLING
|
||||||
|
uchar usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* USB status registers / not shared with asm code */
|
||||||
|
uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
|
||||||
|
static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */
|
||||||
|
static uchar usbMsgFlags; /* flag values see below */
|
||||||
|
|
||||||
|
#define USB_FLG_MSGPTR_IS_ROM (1<<6)
|
||||||
|
#define USB_FLG_USE_USER_RW (1<<7)
|
||||||
|
|
||||||
|
/*
|
||||||
|
optimizing hints:
|
||||||
|
- do not post/pre inc/dec integer values in operations
|
||||||
|
- assign value of USB_READ_FLASH() to register variables and don't use side effects in arg
|
||||||
|
- use narrow scope for variables which should be in X/Y/Z register
|
||||||
|
- assign char sized expressions to variables to force 8 bit arithmetics
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------- String Descriptors --------------------------- */
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_STRINGS == 0
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_STRING_0 == 0
|
||||||
|
#undef USB_CFG_DESCR_PROPS_STRING_0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0)
|
||||||
|
const PROGMEM char usbDescriptorString0[] = { /* language descriptor */
|
||||||
|
4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */
|
||||||
|
3, /* descriptor type */
|
||||||
|
0x09, 0x04, /* language index (0x0409 = US-English) */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN
|
||||||
|
#undef USB_CFG_DESCR_PROPS_STRING_VENDOR
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor)
|
||||||
|
const PROGMEM int usbDescriptorStringVendor[] = {
|
||||||
|
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN),
|
||||||
|
USB_CFG_VENDOR_NAME
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN
|
||||||
|
#undef USB_CFG_DESCR_PROPS_STRING_PRODUCT
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT sizeof(usbDescriptorStringDevice)
|
||||||
|
const PROGMEM int usbDescriptorStringDevice[] = {
|
||||||
|
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN),
|
||||||
|
USB_CFG_DEVICE_NAME
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN
|
||||||
|
#undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber)
|
||||||
|
const PROGMEM int usbDescriptorStringSerialNumber[] = {
|
||||||
|
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
|
||||||
|
USB_CFG_SERIAL_NUMBER
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USB_CFG_DESCR_PROPS_STRINGS == 0 */
|
||||||
|
|
||||||
|
/* --------------------------- Device Descriptor --------------------------- */
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_DEVICE == 0
|
||||||
|
#undef USB_CFG_DESCR_PROPS_DEVICE
|
||||||
|
#define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice)
|
||||||
|
const PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
|
||||||
|
18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
|
||||||
|
USBDESCR_DEVICE, /* descriptor type */
|
||||||
|
0x10, 0x01, /* USB version supported */
|
||||||
|
USB_CFG_DEVICE_CLASS,
|
||||||
|
USB_CFG_DEVICE_SUBCLASS,
|
||||||
|
0, /* protocol */
|
||||||
|
8, /* max packet size */
|
||||||
|
/* the following two casts affect the first byte of the constant only, but
|
||||||
|
* that's sufficient to avoid a warning with the default values.
|
||||||
|
*/
|
||||||
|
(char)USB_CFG_VENDOR_ID,/* 2 bytes */
|
||||||
|
(char)USB_CFG_DEVICE_ID,/* 2 bytes */
|
||||||
|
USB_CFG_DEVICE_VERSION, /* 2 bytes */
|
||||||
|
USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0, /* manufacturer string index */
|
||||||
|
USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0, /* product string index */
|
||||||
|
USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0, /* serial number string index */
|
||||||
|
1, /* number of configurations */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ----------------------- Configuration Descriptor ------------------------ */
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0
|
||||||
|
#undef USB_CFG_DESCR_PROPS_HID
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID 9 /* length of HID descriptor in config descriptor below */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
|
||||||
|
#undef USB_CFG_DESCR_PROPS_CONFIGURATION
|
||||||
|
#define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration)
|
||||||
|
const PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
|
||||||
|
9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
|
||||||
|
USBDESCR_CONFIG, /* descriptor type */
|
||||||
|
18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 +
|
||||||
|
(USB_CFG_DESCR_PROPS_HID & 0xff), 0,
|
||||||
|
/* total length of data returned (including inlined descriptors) */
|
||||||
|
1, /* number of interfaces in this configuration */
|
||||||
|
1, /* index of this configuration */
|
||||||
|
0, /* configuration name string index */
|
||||||
|
#if USB_CFG_IS_SELF_POWERED
|
||||||
|
(1 << 7) | USBATTR_SELFPOWER, /* attributes */
|
||||||
|
#else
|
||||||
|
(1 << 7), /* attributes */
|
||||||
|
#endif
|
||||||
|
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
|
||||||
|
/* interface descriptor follows inline: */
|
||||||
|
9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
|
||||||
|
USBDESCR_INTERFACE, /* descriptor type */
|
||||||
|
0, /* index of this interface */
|
||||||
|
0, /* alternate setting for this interface */
|
||||||
|
USB_CFG_HAVE_INTRIN_ENDPOINT + USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
|
||||||
|
USB_CFG_INTERFACE_CLASS,
|
||||||
|
USB_CFG_INTERFACE_SUBCLASS,
|
||||||
|
USB_CFG_INTERFACE_PROTOCOL,
|
||||||
|
0, /* string index for interface */
|
||||||
|
#if (USB_CFG_DESCR_PROPS_HID & 0xff) /* HID descriptor */
|
||||||
|
9, /* sizeof(usbDescrHID): length of descriptor in bytes */
|
||||||
|
USBDESCR_HID, /* descriptor type: HID */
|
||||||
|
0x01, 0x01, /* BCD representation of HID version */
|
||||||
|
0x00, /* target country code */
|
||||||
|
0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
|
||||||
|
0x22, /* descriptor type: report */
|
||||||
|
USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report descriptor */
|
||||||
|
#endif
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
|
||||||
|
7, /* sizeof(usbDescrEndpoint) */
|
||||||
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
||||||
|
(char)0x81, /* IN endpoint number 1 */
|
||||||
|
0x03, /* attrib: Interrupt endpoint */
|
||||||
|
8, 0, /* maximum packet size */
|
||||||
|
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
|
||||||
|
#endif
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
|
||||||
|
7, /* sizeof(usbDescrEndpoint) */
|
||||||
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
||||||
|
(char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
|
||||||
|
0x03, /* attrib: Interrupt endpoint */
|
||||||
|
8, 0, /* maximum packet size */
|
||||||
|
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline void usbResetDataToggling(void)
|
||||||
|
{
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
|
||||||
|
USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
|
||||||
|
# if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void usbResetStall(void)
|
||||||
|
{
|
||||||
|
#if USB_CFG_IMPLEMENT_HALT && USB_CFG_HAVE_INTRIN_ENDPOINT
|
||||||
|
usbTxLen1 = USBPID_NAK;
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
usbTxLen3 = USBPID_NAK;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if !USB_CFG_SUPPRESS_INTR_CODE
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT
|
||||||
|
static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus)
|
||||||
|
{
|
||||||
|
uchar *p;
|
||||||
|
char i;
|
||||||
|
|
||||||
|
#if USB_CFG_IMPLEMENT_HALT
|
||||||
|
if(usbTxLen1 == USBPID_STALL)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
if(txStatus->len & 0x10){ /* packet buffer was empty */
|
||||||
|
txStatus->buffer[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */
|
||||||
|
}else{
|
||||||
|
txStatus->len = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */
|
||||||
|
}
|
||||||
|
p = txStatus->buffer + 1;
|
||||||
|
i = len;
|
||||||
|
do{ /* if len == 0, we still copy 1 byte, but that's no problem */
|
||||||
|
*p++ = *data++;
|
||||||
|
}while(--i > 0); /* loop control at the end is 2 bytes shorter than at beginning */
|
||||||
|
usbCrc16Append(&txStatus->buffer[1], len);
|
||||||
|
txStatus->len = len + 4; /* len must be given including sync byte */
|
||||||
|
DBG2(0x21 + (((int)txStatus >> 3) & 3), txStatus->buffer, len + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len)
|
||||||
|
{
|
||||||
|
usbGenericSetInterrupt(data, len, &usbTxStatus1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
|
||||||
|
{
|
||||||
|
usbGenericSetInterrupt(data, len, &usbTxStatus3);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* USB_CFG_SUPPRESS_INTR_CODE */
|
||||||
|
|
||||||
|
/* ------------------ utilities for code following below ------------------- */
|
||||||
|
|
||||||
|
/* Use defines for the switch statement so that we can choose between an
|
||||||
|
* if()else if() and a switch/case based implementation. switch() is more
|
||||||
|
* efficient for a LARGE set of sequential choices, if() is better in all other
|
||||||
|
* cases.
|
||||||
|
*/
|
||||||
|
#if USB_CFG_USE_SWITCH_STATEMENT
|
||||||
|
# define SWITCH_START(cmd) switch(cmd){{
|
||||||
|
# define SWITCH_CASE(value) }break; case (value):{
|
||||||
|
# define SWITCH_CASE2(v1,v2) }break; case (v1): case(v2):{
|
||||||
|
# define SWITCH_CASE3(v1,v2,v3) }break; case (v1): case(v2): case(v3):{
|
||||||
|
# define SWITCH_DEFAULT }break; default:{
|
||||||
|
# define SWITCH_END }}
|
||||||
|
#else
|
||||||
|
# define SWITCH_START(cmd) {uchar _cmd = cmd; if(0){
|
||||||
|
# define SWITCH_CASE(value) }else if(_cmd == (value)){
|
||||||
|
# define SWITCH_CASE2(v1,v2) }else if(_cmd == (v1) || _cmd == (v2)){
|
||||||
|
# define SWITCH_CASE3(v1,v2,v3) }else if(_cmd == (v1) || _cmd == (v2) || (_cmd == v3)){
|
||||||
|
# define SWITCH_DEFAULT }else{
|
||||||
|
# define SWITCH_END }}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USB_RX_USER_HOOK
|
||||||
|
#define USB_RX_USER_HOOK(data, len)
|
||||||
|
#endif
|
||||||
|
#ifndef USB_SET_ADDRESS_HOOK
|
||||||
|
#define USB_SET_ADDRESS_HOOK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* We use if() instead of #if in the macro below because #if can't be used
|
||||||
|
* in macros and the compiler optimizes constant conditions anyway.
|
||||||
|
* This may cause problems with undefined symbols if compiled without
|
||||||
|
* optimizing!
|
||||||
|
*/
|
||||||
|
#define GET_DESCRIPTOR(cfgProp, staticName) \
|
||||||
|
if(cfgProp){ \
|
||||||
|
if((cfgProp) & USB_PROP_IS_RAM) \
|
||||||
|
flags = 0; \
|
||||||
|
if((cfgProp) & USB_PROP_IS_DYNAMIC){ \
|
||||||
|
len = usbFunctionDescriptor(rq); \
|
||||||
|
}else{ \
|
||||||
|
len = USB_PROP_LENGTH(cfgProp); \
|
||||||
|
usbMsgPtr = (uchar *)(staticName); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used
|
||||||
|
* internally for all types of descriptors.
|
||||||
|
*/
|
||||||
|
static inline usbMsgLen_t usbDriverDescriptor(usbRequest_t *rq)
|
||||||
|
{
|
||||||
|
usbMsgLen_t len = 0;
|
||||||
|
uchar flags = USB_FLG_MSGPTR_IS_ROM;
|
||||||
|
|
||||||
|
SWITCH_START(rq->wValue.bytes[1])
|
||||||
|
SWITCH_CASE(USBDESCR_DEVICE) /* 1 */
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice)
|
||||||
|
SWITCH_CASE(USBDESCR_CONFIG) /* 2 */
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration)
|
||||||
|
SWITCH_CASE(USBDESCR_STRING) /* 3 */
|
||||||
|
#if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC
|
||||||
|
if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM)
|
||||||
|
flags = 0;
|
||||||
|
len = usbFunctionDescriptor(rq);
|
||||||
|
#else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */
|
||||||
|
SWITCH_START(rq->wValue.bytes[0])
|
||||||
|
SWITCH_CASE(0)
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0)
|
||||||
|
SWITCH_CASE(1)
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor)
|
||||||
|
SWITCH_CASE(2)
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice)
|
||||||
|
SWITCH_CASE(3)
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber)
|
||||||
|
SWITCH_DEFAULT
|
||||||
|
if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){
|
||||||
|
len = usbFunctionDescriptor(rq);
|
||||||
|
}
|
||||||
|
SWITCH_END
|
||||||
|
#endif /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */
|
||||||
|
#if USB_CFG_DESCR_PROPS_HID_REPORT /* only support HID descriptors if enabled */
|
||||||
|
SWITCH_CASE(USBDESCR_HID) /* 0x21 */
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18)
|
||||||
|
SWITCH_CASE(USBDESCR_HID_REPORT)/* 0x22 */
|
||||||
|
GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport)
|
||||||
|
#endif
|
||||||
|
SWITCH_DEFAULT
|
||||||
|
if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){
|
||||||
|
len = usbFunctionDescriptor(rq);
|
||||||
|
}
|
||||||
|
SWITCH_END
|
||||||
|
usbMsgFlags = flags;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for
|
||||||
|
* standard requests instead of class and custom requests.
|
||||||
|
*/
|
||||||
|
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
|
||||||
|
{
|
||||||
|
uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
|
||||||
|
uchar value = rq->wValue.bytes[0];
|
||||||
|
#if USB_CFG_IMPLEMENT_HALT
|
||||||
|
uchar index = rq->wIndex.bytes[0];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dataPtr[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */
|
||||||
|
SWITCH_START(rq->bRequest)
|
||||||
|
SWITCH_CASE(USBRQ_GET_STATUS) /* 0 */
|
||||||
|
uchar recipient = rq->bmRequestType & USBRQ_RCPT_MASK; /* assign arith ops to variables to enforce byte size */
|
||||||
|
if(USB_CFG_IS_SELF_POWERED && recipient == USBRQ_RCPT_DEVICE)
|
||||||
|
dataPtr[0] = USB_CFG_IS_SELF_POWERED;
|
||||||
|
#if USB_CFG_IMPLEMENT_HALT
|
||||||
|
if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81) /* request status for endpoint 1 */
|
||||||
|
dataPtr[0] = usbTxLen1 == USBPID_STALL;
|
||||||
|
#endif
|
||||||
|
dataPtr[1] = 0;
|
||||||
|
len = 2;
|
||||||
|
#if USB_CFG_IMPLEMENT_HALT
|
||||||
|
SWITCH_CASE2(USBRQ_CLEAR_FEATURE, USBRQ_SET_FEATURE) /* 1, 3 */
|
||||||
|
if(value == 0 && index == 0x81){ /* feature 0 == HALT for endpoint == 1 */
|
||||||
|
usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL;
|
||||||
|
usbResetDataToggling();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
SWITCH_CASE(USBRQ_SET_ADDRESS) /* 5 */
|
||||||
|
usbNewDeviceAddr = value;
|
||||||
|
USB_SET_ADDRESS_HOOK();
|
||||||
|
SWITCH_CASE(USBRQ_GET_DESCRIPTOR) /* 6 */
|
||||||
|
len = usbDriverDescriptor(rq);
|
||||||
|
goto skipMsgPtrAssignment;
|
||||||
|
SWITCH_CASE(USBRQ_GET_CONFIGURATION) /* 8 */
|
||||||
|
dataPtr = &usbConfiguration; /* send current configuration value */
|
||||||
|
len = 1;
|
||||||
|
SWITCH_CASE(USBRQ_SET_CONFIGURATION) /* 9 */
|
||||||
|
usbConfiguration = value;
|
||||||
|
usbResetStall();
|
||||||
|
SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */
|
||||||
|
len = 1;
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
|
||||||
|
SWITCH_CASE(USBRQ_SET_INTERFACE) /* 11 */
|
||||||
|
usbResetDataToggling();
|
||||||
|
usbResetStall();
|
||||||
|
#endif
|
||||||
|
SWITCH_DEFAULT /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */
|
||||||
|
/* Should we add an optional hook here? */
|
||||||
|
SWITCH_END
|
||||||
|
usbMsgPtr = dataPtr;
|
||||||
|
skipMsgPtrAssignment:
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* usbProcessRx() is called for every message received by the interrupt
|
||||||
|
* routine. It distinguishes between SETUP and DATA packets and processes
|
||||||
|
* them accordingly.
|
||||||
|
*/
|
||||||
|
static inline void usbProcessRx(uchar *data, uchar len)
|
||||||
|
{
|
||||||
|
usbRequest_t *rq = (void *)data;
|
||||||
|
|
||||||
|
/* usbRxToken can be:
|
||||||
|
* 0x2d 00101101 (USBPID_SETUP for setup data)
|
||||||
|
* 0xe1 11100001 (USBPID_OUT: data phase of setup transfer)
|
||||||
|
* 0...0x0f for OUT on endpoint X
|
||||||
|
*/
|
||||||
|
DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
|
||||||
|
USB_RX_USER_HOOK(data, len)
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
|
||||||
|
if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */
|
||||||
|
usbFunctionWriteOut(data, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(usbRxToken == (uchar)USBPID_SETUP){
|
||||||
|
if(len != 8) /* Setup size must be always 8 bytes. Ignore otherwise. */
|
||||||
|
return;
|
||||||
|
usbMsgLen_t replyLen;
|
||||||
|
usbTxBuf[0] = USBPID_DATA0; /* initialize data toggling */
|
||||||
|
usbTxLen = USBPID_NAK; /* abort pending transmit */
|
||||||
|
usbMsgFlags = 0;
|
||||||
|
uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;
|
||||||
|
if(type != USBRQ_TYPE_STANDARD){ /* standard requests are handled by driver */
|
||||||
|
replyLen = usbFunctionSetup(data);
|
||||||
|
}else{
|
||||||
|
replyLen = usbDriverSetup(rq);
|
||||||
|
}
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
|
||||||
|
if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */
|
||||||
|
/* do some conditioning on replyLen, but on IN transfers only */
|
||||||
|
if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){
|
||||||
|
if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
|
||||||
|
replyLen = rq->wLength.bytes[0];
|
||||||
|
}else{
|
||||||
|
replyLen = rq->wLength.word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usbMsgFlags = USB_FLG_USE_USER_RW;
|
||||||
|
}else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */
|
||||||
|
#endif
|
||||||
|
if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
|
||||||
|
if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0]) /* limit length to max */
|
||||||
|
replyLen = rq->wLength.bytes[0];
|
||||||
|
}else{
|
||||||
|
if(replyLen > rq->wLength.word) /* limit length to max */
|
||||||
|
replyLen = rq->wLength.word;
|
||||||
|
}
|
||||||
|
usbMsgLen = replyLen;
|
||||||
|
}else{ /* usbRxToken must be USBPID_OUT, which means data phase of setup (control-out) */
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_WRITE
|
||||||
|
if(usbMsgFlags & USB_FLG_USE_USER_RW){
|
||||||
|
uchar rval = usbFunctionWrite(data, len);
|
||||||
|
if(rval == 0xff){ /* an error occurred */
|
||||||
|
usbTxLen = USBPID_STALL;
|
||||||
|
}else if(rval != 0){ /* This was the final package */
|
||||||
|
usbMsgLen = 0; /* answer with a zero-sized data packet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* This function is similar to usbFunctionRead(), but it's also called for
|
||||||
|
* data handled automatically by the driver (e.g. descriptor reads).
|
||||||
|
*/
|
||||||
|
static uchar usbDeviceRead(uchar *data, uchar len)
|
||||||
|
{
|
||||||
|
if(len > 0){ /* don't bother app with 0 sized reads */
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_READ
|
||||||
|
if(usbMsgFlags & USB_FLG_USE_USER_RW){
|
||||||
|
len = usbFunctionRead(data, len);
|
||||||
|
}else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
uchar i = len, *r = usbMsgPtr;
|
||||||
|
if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
|
||||||
|
do{
|
||||||
|
uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */
|
||||||
|
*data++ = c;
|
||||||
|
r++;
|
||||||
|
}while(--i);
|
||||||
|
}else{ /* RAM data */
|
||||||
|
do{
|
||||||
|
*data++ = *r++;
|
||||||
|
}while(--i);
|
||||||
|
}
|
||||||
|
usbMsgPtr = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* usbBuildTxBlock() is called when we have data to transmit and the
|
||||||
|
* interrupt routine's transmit buffer is empty.
|
||||||
|
*/
|
||||||
|
static inline void usbBuildTxBlock(void)
|
||||||
|
{
|
||||||
|
usbMsgLen_t wantLen;
|
||||||
|
uchar len;
|
||||||
|
|
||||||
|
wantLen = usbMsgLen;
|
||||||
|
if(wantLen > 8)
|
||||||
|
wantLen = 8;
|
||||||
|
usbMsgLen -= wantLen;
|
||||||
|
usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */
|
||||||
|
len = usbDeviceRead(usbTxBuf + 1, wantLen);
|
||||||
|
if(len <= 8){ /* valid data packet */
|
||||||
|
usbCrc16Append(&usbTxBuf[1], len);
|
||||||
|
len += 4; /* length including sync byte */
|
||||||
|
if(len < 12) /* a partial package identifies end of message */
|
||||||
|
usbMsgLen = USB_NO_MSG;
|
||||||
|
}else{
|
||||||
|
len = USBPID_STALL; /* stall the endpoint */
|
||||||
|
usbMsgLen = USB_NO_MSG;
|
||||||
|
}
|
||||||
|
usbTxLen = len;
|
||||||
|
DBG2(0x20, usbTxBuf, len-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline void usbHandleResetHook(uchar notResetState)
|
||||||
|
{
|
||||||
|
#ifdef USB_RESET_HOOK
|
||||||
|
static uchar wasReset;
|
||||||
|
uchar isReset = !notResetState;
|
||||||
|
|
||||||
|
if(wasReset != isReset){
|
||||||
|
USB_RESET_HOOK(isReset);
|
||||||
|
wasReset = isReset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
USB_PUBLIC void usbPoll(void)
|
||||||
|
{
|
||||||
|
schar len;
|
||||||
|
uchar i;
|
||||||
|
|
||||||
|
len = usbRxLen - 3;
|
||||||
|
if(len >= 0){
|
||||||
|
/* We could check CRC16 here -- but ACK has already been sent anyway. If you
|
||||||
|
* need data integrity checks with this driver, check the CRC in your app
|
||||||
|
* code and report errors back to the host. Since the ACK was already sent,
|
||||||
|
* retries must be handled on application level.
|
||||||
|
* unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3);
|
||||||
|
*/
|
||||||
|
usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len);
|
||||||
|
#if USB_CFG_HAVE_FLOWCONTROL
|
||||||
|
if(usbRxLen > 0) /* only mark as available if not inactivated */
|
||||||
|
usbRxLen = 0;
|
||||||
|
#else
|
||||||
|
usbRxLen = 0; /* mark rx buffer as available */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if(usbTxLen & 0x10){ /* transmit system idle */
|
||||||
|
if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */
|
||||||
|
usbBuildTxBlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(i = 20; i > 0; i--){
|
||||||
|
uchar usbLineStatus = USBIN & USBMASK;
|
||||||
|
if(usbLineStatus != 0) /* SE0 has ended */
|
||||||
|
goto isNotReset;
|
||||||
|
}
|
||||||
|
/* RESET condition, called multiple times during reset */
|
||||||
|
usbNewDeviceAddr = 0;
|
||||||
|
usbDeviceAddr = 0;
|
||||||
|
usbResetStall();
|
||||||
|
DBG1(0xff, 0, 0);
|
||||||
|
isNotReset:
|
||||||
|
usbHandleResetHook(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
USB_PUBLIC void usbInit(void)
|
||||||
|
{
|
||||||
|
#if USB_INTR_CFG_SET != 0
|
||||||
|
USB_INTR_CFG |= USB_INTR_CFG_SET;
|
||||||
|
#endif
|
||||||
|
#if USB_INTR_CFG_CLR != 0
|
||||||
|
USB_INTR_CFG &= ~(USB_INTR_CFG_CLR);
|
||||||
|
#endif
|
||||||
|
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
|
||||||
|
usbResetDataToggling();
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
|
||||||
|
usbTxLen1 = USBPID_NAK;
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
usbTxLen3 = USBPID_NAK;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
790
hardware/digistump/avr/libraries/DigiCDC/usbdrv.h
Normal file
790
hardware/digistump/avr/libraries/DigiCDC/usbdrv.h
Normal file
@ -0,0 +1,790 @@
|
|||||||
|
/* Name: usbdrv.h
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2004-12-29
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: usbdrv.h 793 2010-07-15 15:58:11Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __usbdrv_h_included__
|
||||||
|
#define __usbdrv_h_included__
|
||||||
|
#include "usbconfig.h"
|
||||||
|
#include "usbportability.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Hardware Prerequisites:
|
||||||
|
=======================
|
||||||
|
USB lines D+ and D- MUST be wired to the same I/O port. We recommend that D+
|
||||||
|
triggers the interrupt (best achieved by using INT0 for D+), but it is also
|
||||||
|
possible to trigger the interrupt from D-. If D- is used, interrupts are also
|
||||||
|
triggered by SOF packets. D- requires a pull-up of 1.5k to +3.5V (and the
|
||||||
|
device must be powered at 3.5V) to identify as low-speed USB device. A
|
||||||
|
pull-down or pull-up of 1M SHOULD be connected from D+ to +3.5V to prevent
|
||||||
|
interference when no USB master is connected. If you use Zener diodes to limit
|
||||||
|
the voltage on D+ and D-, you MUST use a pull-down resistor, not a pull-up.
|
||||||
|
We use D+ as interrupt source and not D- because it does not trigger on
|
||||||
|
keep-alive and RESET states. If you want to count keep-alive events with
|
||||||
|
USB_COUNT_SOF, you MUST use D- as an interrupt source.
|
||||||
|
|
||||||
|
As a compile time option, the 1.5k pull-up resistor on D- can be made
|
||||||
|
switchable to allow the device to disconnect at will. See the definition of
|
||||||
|
usbDeviceConnect() and usbDeviceDisconnect() further down in this file.
|
||||||
|
|
||||||
|
Please adapt the values in usbconfig.h according to your hardware!
|
||||||
|
|
||||||
|
The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz
|
||||||
|
or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details.
|
||||||
|
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
============
|
||||||
|
Robustness with respect to communication errors:
|
||||||
|
The driver assumes error-free communication. It DOES check for errors in
|
||||||
|
the PID, but does NOT check bit stuffing errors, SE0 in middle of a byte,
|
||||||
|
token CRC (5 bit) and data CRC (16 bit). CRC checks can not be performed due
|
||||||
|
to timing constraints: We must start sending a reply within 7 bit times.
|
||||||
|
Bit stuffing and misplaced SE0 would have to be checked in real-time, but CPU
|
||||||
|
performance does not permit that. The driver does not check Data0/Data1
|
||||||
|
toggling, but application software can implement the check.
|
||||||
|
|
||||||
|
Input characteristics:
|
||||||
|
Since no differential receiver circuit is used, electrical interference
|
||||||
|
robustness may suffer. The driver samples only one of the data lines with
|
||||||
|
an ordinary I/O pin's input characteristics. However, since this is only a
|
||||||
|
low speed USB implementation and the specification allows for 8 times the
|
||||||
|
bit rate over the same hardware, we should be on the safe side. Even the spec
|
||||||
|
requires detection of asymmetric states at high bit rate for SE0 detection.
|
||||||
|
|
||||||
|
Number of endpoints:
|
||||||
|
The driver supports the following endpoints:
|
||||||
|
|
||||||
|
- Endpoint 0, the default control endpoint.
|
||||||
|
- Any number of interrupt- or bulk-out endpoints. The data is sent to
|
||||||
|
usbFunctionWriteOut() and USB_CFG_IMPLEMENT_FN_WRITEOUT must be defined
|
||||||
|
to 1 to activate this feature. The endpoint number can be found in the
|
||||||
|
global variable 'usbRxToken'.
|
||||||
|
- One default interrupt- or bulk-in endpoint. This endpoint is used for
|
||||||
|
interrupt- or bulk-in transfers which are not handled by any other endpoint.
|
||||||
|
You must define USB_CFG_HAVE_INTRIN_ENDPOINT in order to activate this
|
||||||
|
feature and call usbSetInterrupt() to send interrupt/bulk data.
|
||||||
|
- One additional interrupt- or bulk-in endpoint. This was endpoint 3 in
|
||||||
|
previous versions of this driver but can now be configured to any endpoint
|
||||||
|
number. You must define USB_CFG_HAVE_INTRIN_ENDPOINT3 in order to activate
|
||||||
|
this feature and call usbSetInterrupt3() to send interrupt/bulk data. The
|
||||||
|
endpoint number can be set with USB_CFG_EP3_NUMBER.
|
||||||
|
|
||||||
|
Please note that the USB standard forbids bulk endpoints for low speed devices!
|
||||||
|
Most operating systems allow them anyway, but the AVR will spend 90% of the CPU
|
||||||
|
time in the USB interrupt polling for bulk data.
|
||||||
|
|
||||||
|
Maximum data payload:
|
||||||
|
Data payload of control in and out transfers may be up to 254 bytes. In order
|
||||||
|
to accept payload data of out transfers, you need to implement
|
||||||
|
'usbFunctionWrite()'.
|
||||||
|
|
||||||
|
USB Suspend Mode supply current:
|
||||||
|
The USB standard limits power consumption to 500uA when the bus is in suspend
|
||||||
|
mode. This is not a problem for self-powered devices since they don't need
|
||||||
|
bus power anyway. Bus-powered devices can achieve this only by putting the
|
||||||
|
CPU in sleep mode. The driver does not implement suspend handling by itself.
|
||||||
|
However, the application may implement activity monitoring and wakeup from
|
||||||
|
sleep. The host sends regular SE0 states on the bus to keep it active. These
|
||||||
|
SE0 states can be detected by using D- as the interrupt source. Define
|
||||||
|
USB_COUNT_SOF to 1 and use the global variable usbSofCount to check for bus
|
||||||
|
activity.
|
||||||
|
|
||||||
|
Operation without an USB master:
|
||||||
|
The driver behaves neutral without connection to an USB master if D- reads
|
||||||
|
as 1. To avoid spurious interrupts, we recommend a high impedance (e.g. 1M)
|
||||||
|
pull-down or pull-up resistor on D+ (interrupt). If Zener diodes are used,
|
||||||
|
use a pull-down. If D- becomes statically 0, the driver may block in the
|
||||||
|
interrupt routine.
|
||||||
|
|
||||||
|
Interrupt latency:
|
||||||
|
The application must ensure that the USB interrupt is not disabled for more
|
||||||
|
than 25 cycles (this is for 12 MHz, faster clocks allow longer latency).
|
||||||
|
This implies that all interrupt routines must either have the "ISR_NOBLOCK"
|
||||||
|
attribute set (see "avr/interrupt.h") or be written in assembler with "sei"
|
||||||
|
as the first instruction.
|
||||||
|
|
||||||
|
Maximum interrupt duration / CPU cycle consumption:
|
||||||
|
The driver handles all USB communication during the interrupt service
|
||||||
|
routine. The routine will not return before an entire USB message is received
|
||||||
|
and the reply is sent. This may be up to ca. 1200 cycles @ 12 MHz (= 100us) if
|
||||||
|
the host conforms to the standard. The driver will consume CPU cycles for all
|
||||||
|
USB messages, even if they address another (low-speed) device on the same bus.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --------------------------- Module Interface ---------------------------- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define USBDRV_VERSION 20100715
|
||||||
|
/* This define uniquely identifies a driver version. It is a decimal number
|
||||||
|
* constructed from the driver's release date in the form YYYYMMDD. If the
|
||||||
|
* driver's behavior or interface changes, you can use this constant to
|
||||||
|
* distinguish versions. If it is not defined, the driver's release date is
|
||||||
|
* older than 2006-01-25.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef USB_PUBLIC
|
||||||
|
#define USB_PUBLIC
|
||||||
|
#endif
|
||||||
|
/* USB_PUBLIC is used as declaration attribute for all functions exported by
|
||||||
|
* the USB driver. The default is no attribute (see above). You may define it
|
||||||
|
* to static either in usbconfig.h or from the command line if you include
|
||||||
|
* usbdrv.c instead of linking against it. Including the C module of the driver
|
||||||
|
* directly in your code saves a couple of bytes in flash memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
#ifndef uchar
|
||||||
|
#define uchar unsigned char
|
||||||
|
#endif
|
||||||
|
#ifndef schar
|
||||||
|
#define schar signed char
|
||||||
|
#endif
|
||||||
|
/* shortcuts for well defined 8 bit integer types */
|
||||||
|
|
||||||
|
#if USB_CFG_LONG_TRANSFERS /* if more than 254 bytes transfer size required */
|
||||||
|
# define usbMsgLen_t unsigned
|
||||||
|
#else
|
||||||
|
# define usbMsgLen_t uchar
|
||||||
|
#endif
|
||||||
|
/* usbMsgLen_t is the data type used for transfer lengths. By default, it is
|
||||||
|
* defined to uchar, allowing a maximum of 254 bytes (255 is reserved for
|
||||||
|
* USB_NO_MSG below). If the usbconfig.h defines USB_CFG_LONG_TRANSFERS to 1,
|
||||||
|
* a 16 bit data type is used, allowing up to 16384 bytes (the rest is used
|
||||||
|
* for flags in the descriptor configuration).
|
||||||
|
*/
|
||||||
|
#define USB_NO_MSG ((usbMsgLen_t)-1) /* constant meaning "no message" */
|
||||||
|
|
||||||
|
struct usbRequest; /* forward declaration */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
USB_PUBLIC void usbInit(void);
|
||||||
|
/* This function must be called before interrupts are enabled and the main
|
||||||
|
* loop is entered. We exepct that the PORT and DDR bits for D+ and D- have
|
||||||
|
* not been changed from their default status (which is 0). If you have changed
|
||||||
|
* them, set both back to 0 (configure them as input with no internal pull-up).
|
||||||
|
*/
|
||||||
|
USB_PUBLIC void usbPoll(void);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
/* This function must be called at regular intervals from the main loop.
|
||||||
|
* Maximum delay between calls is somewhat less than 50ms (USB timeout for
|
||||||
|
* accepting a Setup message). Otherwise the device will not be recognized.
|
||||||
|
* Please note that debug outputs through the UART take ~ 0.5ms per byte
|
||||||
|
* at 19200 bps.
|
||||||
|
*/
|
||||||
|
extern uchar *usbMsgPtr;
|
||||||
|
/* This variable may be used to pass transmit data to the driver from the
|
||||||
|
* implementation of usbFunctionWrite(). It is also used internally by the
|
||||||
|
* driver for standard control requests.
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]);
|
||||||
|
/* This function is called when the driver receives a SETUP transaction from
|
||||||
|
* the host which is not answered by the driver itself (in practice: class and
|
||||||
|
* vendor requests). All control transfers start with a SETUP transaction where
|
||||||
|
* the host communicates the parameters of the following (optional) data
|
||||||
|
* transfer. The SETUP data is available in the 'data' parameter which can
|
||||||
|
* (and should) be casted to 'usbRequest_t *' for a more user-friendly access
|
||||||
|
* to parameters.
|
||||||
|
*
|
||||||
|
* If the SETUP indicates a control-in transfer, you should provide the
|
||||||
|
* requested data to the driver. There are two ways to transfer this data:
|
||||||
|
* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data
|
||||||
|
* block and return the length of the data in 'usbFunctionSetup()'. The driver
|
||||||
|
* will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The
|
||||||
|
* driver will then call 'usbFunctionRead()' when data is needed. See the
|
||||||
|
* documentation for usbFunctionRead() for details.
|
||||||
|
*
|
||||||
|
* If the SETUP indicates a control-out transfer, the only way to receive the
|
||||||
|
* data from the host is through the 'usbFunctionWrite()' call. If you
|
||||||
|
* implement this function, you must return USB_NO_MSG in 'usbFunctionSetup()'
|
||||||
|
* to indicate that 'usbFunctionWrite()' should be used. See the documentation
|
||||||
|
* of this function for more information. If you just want to ignore the data
|
||||||
|
* sent by the host, return 0 in 'usbFunctionSetup()'.
|
||||||
|
*
|
||||||
|
* Note that calls to the functions usbFunctionRead() and usbFunctionWrite()
|
||||||
|
* are only done if enabled by the configuration in usbconfig.h.
|
||||||
|
*/
|
||||||
|
USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
/* You need to implement this function ONLY if you provide USB descriptors at
|
||||||
|
* runtime (which is an expert feature). It is very similar to
|
||||||
|
* usbFunctionSetup() above, but it is called only to request USB descriptor
|
||||||
|
* data. See the documentation of usbFunctionSetup() above for more info.
|
||||||
|
*/
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
/* This function sets the message which will be sent during the next interrupt
|
||||||
|
* IN transfer. The message is copied to an internal buffer and must not exceed
|
||||||
|
* a length of 8 bytes. The message may be 0 bytes long just to indicate the
|
||||||
|
* interrupt status to the host.
|
||||||
|
* If you need to transfer more bytes, use a control read after the interrupt.
|
||||||
|
*/
|
||||||
|
#define usbInterruptIsReady() (usbTxLen1 & 0x10)
|
||||||
|
/* This macro indicates whether the last interrupt message has already been
|
||||||
|
* sent. If you set a new interrupt message before the old was sent, the
|
||||||
|
* message already buffered will be lost.
|
||||||
|
*/
|
||||||
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
#define usbInterruptIsReady3() (usbTxLen3 & 0x10)
|
||||||
|
/* Same as above for endpoint 3 */
|
||||||
|
#endif
|
||||||
|
#endif /* USB_CFG_HAVE_INTRIN_ENDPOINT */
|
||||||
|
#if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* simplified interface for backward compatibility */
|
||||||
|
#define usbHidReportDescriptor usbDescriptorHidReport
|
||||||
|
/* should be declared as: const PROGMEM char usbHidReportDescriptor[]; */
|
||||||
|
/* If you implement an HID device, you need to provide a report descriptor.
|
||||||
|
* The HID report descriptor syntax is a bit complex. If you understand how
|
||||||
|
* report descriptors are constructed, we recommend that you use the HID
|
||||||
|
* Descriptor Tool from usb.org, see http://www.usb.org/developers/hidpage/.
|
||||||
|
* Otherwise you should probably start with a working example.
|
||||||
|
*/
|
||||||
|
#endif /* USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH */
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_WRITE
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
/* This function is called by the driver to provide a control transfer's
|
||||||
|
* payload data (control-out). It is called in chunks of up to 8 bytes. The
|
||||||
|
* total count provided in the current control transfer can be obtained from
|
||||||
|
* the 'length' property in the setup data. If an error occurred during
|
||||||
|
* processing, return 0xff (== -1). The driver will answer the entire transfer
|
||||||
|
* with a STALL token in this case. If you have received the entire payload
|
||||||
|
* successfully, return 1. If you expect more data, return 0. If you don't
|
||||||
|
* know whether the host will send more data (you should know, the total is
|
||||||
|
* provided in the usbFunctionSetup() call!), return 1.
|
||||||
|
* NOTE: If you return 0xff for STALL, 'usbFunctionWrite()' may still be called
|
||||||
|
* for the remaining data. You must continue to return 0xff for STALL in these
|
||||||
|
* calls.
|
||||||
|
* In order to get usbFunctionWrite() called, define USB_CFG_IMPLEMENT_FN_WRITE
|
||||||
|
* to 1 in usbconfig.h and return 0xff in usbFunctionSetup()..
|
||||||
|
*/
|
||||||
|
#endif /* USB_CFG_IMPLEMENT_FN_WRITE */
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_READ
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
USB_PUBLIC uchar usbFunctionRead(uchar *data, uchar len);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
/* This function is called by the driver to ask the application for a control
|
||||||
|
* transfer's payload data (control-in). It is called in chunks of up to 8
|
||||||
|
* bytes each. You should copy the data to the location given by 'data' and
|
||||||
|
* return the actual number of bytes copied. If you return less than requested,
|
||||||
|
* the control-in transfer is terminated. If you return 0xff, the driver aborts
|
||||||
|
* the transfer with a STALL token.
|
||||||
|
* In order to get usbFunctionRead() called, define USB_CFG_IMPLEMENT_FN_READ
|
||||||
|
* to 1 in usbconfig.h and return 0xff in usbFunctionSetup()..
|
||||||
|
*/
|
||||||
|
#endif /* USB_CFG_IMPLEMENT_FN_READ */
|
||||||
|
|
||||||
|
extern uchar usbRxToken; /* may be used in usbFunctionWriteOut() below */
|
||||||
|
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
/* This function is called by the driver when data is received on an interrupt-
|
||||||
|
* or bulk-out endpoint. The endpoint number can be found in the global
|
||||||
|
* variable usbRxToken. You must define USB_CFG_IMPLEMENT_FN_WRITEOUT to 1 in
|
||||||
|
* usbconfig.h to get this function called.
|
||||||
|
*/
|
||||||
|
#endif /* USB_CFG_IMPLEMENT_FN_WRITEOUT */
|
||||||
|
#ifdef USB_CFG_PULLUP_IOPORTNAME
|
||||||
|
#define usbDeviceConnect() ((USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT)), \
|
||||||
|
(USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT)))
|
||||||
|
#define usbDeviceDisconnect() ((USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT)), \
|
||||||
|
(USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT)))
|
||||||
|
#else /* USB_CFG_PULLUP_IOPORTNAME */
|
||||||
|
#define usbDeviceConnect() (USBDDR &= ~(1<<USBMINUS))
|
||||||
|
#define usbDeviceDisconnect() (USBDDR |= (1<<USBMINUS))
|
||||||
|
#endif /* USB_CFG_PULLUP_IOPORTNAME */
|
||||||
|
/* The macros usbDeviceConnect() and usbDeviceDisconnect() (intended to look
|
||||||
|
* like a function) connect resp. disconnect the device from the host's USB.
|
||||||
|
* If the constants USB_CFG_PULLUP_IOPORT and USB_CFG_PULLUP_BIT are defined
|
||||||
|
* in usbconfig.h, a disconnect consists of removing the pull-up resisitor
|
||||||
|
* from D-, otherwise the disconnect is done by brute-force pulling D- to GND.
|
||||||
|
* This does not conform to the spec, but it works.
|
||||||
|
* Please note that the USB interrupt must be disabled while the device is
|
||||||
|
* in disconnected state, or the interrupt handler will hang! You can either
|
||||||
|
* turn off the USB interrupt selectively with
|
||||||
|
* USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT)
|
||||||
|
* or use cli() to disable interrupts globally.
|
||||||
|
*/
|
||||||
|
extern unsigned usbCrc16(unsigned data, uchar len);
|
||||||
|
#define usbCrc16(data, len) usbCrc16((unsigned)(data), len)
|
||||||
|
/* This function calculates the binary complement of the data CRC used in
|
||||||
|
* USB data packets. The value is used to build raw transmit packets.
|
||||||
|
* You may want to use this function for data checksums or to verify received
|
||||||
|
* data. We enforce 16 bit calling conventions for compatibility with IAR's
|
||||||
|
* tiny memory model.
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
extern unsigned usbCrc16Append(unsigned data, uchar len);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
#define usbCrc16Append(data, len) usbCrc16Append((unsigned)(data), len)
|
||||||
|
/* This function is equivalent to usbCrc16() above, except that it appends
|
||||||
|
* the 2 bytes CRC (lowbyte first) in the 'data' buffer after reading 'len'
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
|
||||||
|
extern unsigned usbMeasureFrameLength(void);
|
||||||
|
/* This function MUST be called IMMEDIATELY AFTER USB reset and measures 1/7 of
|
||||||
|
* the number of CPU cycles during one USB frame minus one low speed bit
|
||||||
|
* length. In other words: return value = 1499 * (F_CPU / 10.5 MHz)
|
||||||
|
* Since this is a busy wait, you MUST disable all interrupts with cli() before
|
||||||
|
* calling this function.
|
||||||
|
* This can be used to calibrate the AVR's RC oscillator.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
extern uchar usbConfiguration;
|
||||||
|
/* This value contains the current configuration set by the host. The driver
|
||||||
|
* allows setting and querying of this variable with the USB SET_CONFIGURATION
|
||||||
|
* and GET_CONFIGURATION requests, but does not use it otherwise.
|
||||||
|
* You may want to reflect the "configured" status with a LED on the device or
|
||||||
|
* switch on high power parts of the circuit only if the device is configured.
|
||||||
|
*/
|
||||||
|
#if USB_COUNT_SOF
|
||||||
|
extern volatile uchar usbSofCount;
|
||||||
|
/* This variable is incremented on every SOF packet. It is only available if
|
||||||
|
* the macro USB_COUNT_SOF is defined to a value != 0.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
#if USB_CFG_CHECK_DATA_TOGGLING
|
||||||
|
extern uchar usbCurrentDataToken;
|
||||||
|
/* This variable can be checked in usbFunctionWrite() and usbFunctionWriteOut()
|
||||||
|
* to ignore duplicate packets.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8))
|
||||||
|
/* This macro builds a descriptor header for a string descriptor given the
|
||||||
|
* string's length. See usbdrv.c for an example how to use it.
|
||||||
|
*/
|
||||||
|
#if USB_CFG_HAVE_FLOWCONTROL
|
||||||
|
extern volatile schar usbRxLen;
|
||||||
|
#define usbDisableAllRequests() usbRxLen = -1
|
||||||
|
/* Must be called from usbFunctionWrite(). This macro disables all data input
|
||||||
|
* from the USB interface. Requests from the host are answered with a NAK
|
||||||
|
* while they are disabled.
|
||||||
|
*/
|
||||||
|
#define usbEnableAllRequests() usbRxLen = 0
|
||||||
|
/* May only be called if requests are disabled. This macro enables input from
|
||||||
|
* the USB interface after it has been disabled with usbDisableAllRequests().
|
||||||
|
*/
|
||||||
|
#define usbAllRequestsAreDisabled() (usbRxLen < 0)
|
||||||
|
/* Use this macro to find out whether requests are disabled. It may be needed
|
||||||
|
* to ensure that usbEnableAllRequests() is never called when requests are
|
||||||
|
* enabled.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_SET_DATATOKEN1(token) usbTxBuf1[0] = token
|
||||||
|
#define USB_SET_DATATOKEN3(token) usbTxBuf3[0] = token
|
||||||
|
/* These two macros can be used by application software to reset data toggling
|
||||||
|
* for interrupt-in endpoints 1 and 3. Since the token is toggled BEFORE
|
||||||
|
* sending data, you must set the opposite value of the token which should come
|
||||||
|
* first.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* ----------------- Definitions for Descriptor Properties ----------------- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* This is advanced stuff. See usbconfig-prototype.h for more information
|
||||||
|
* about the various methods to define USB descriptors. If you do nothing,
|
||||||
|
* the default descriptors will be used.
|
||||||
|
*/
|
||||||
|
#define USB_PROP_IS_DYNAMIC (1 << 14)
|
||||||
|
/* If this property is set for a descriptor, usbFunctionDescriptor() will be
|
||||||
|
* used to obtain the particular descriptor. Data directly returned via
|
||||||
|
* usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to
|
||||||
|
* return RAM data.
|
||||||
|
*/
|
||||||
|
#define USB_PROP_IS_RAM (1 << 15)
|
||||||
|
/* If this property is set for a descriptor, the data is read from RAM
|
||||||
|
* memory instead of Flash. The property is used for all methods to provide
|
||||||
|
* external descriptors.
|
||||||
|
*/
|
||||||
|
#define USB_PROP_LENGTH(len) ((len) & 0x3fff)
|
||||||
|
/* If a static external descriptor is used, this is the total length of the
|
||||||
|
* descriptor in bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* all descriptors which may have properties: */
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_DEVICE
|
||||||
|
#define USB_CFG_DESCR_PROPS_DEVICE 0
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_CONFIGURATION
|
||||||
|
#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_STRINGS
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRINGS 0
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_STRING_0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_0 0
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_STRING_VENDOR
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_STRING_PRODUCT
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_HID
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID 0
|
||||||
|
#endif
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_HID_REPORT)
|
||||||
|
# undef USB_CFG_DESCR_PROPS_HID_REPORT
|
||||||
|
# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* do some backward compatibility tricks */
|
||||||
|
# define USB_CFG_DESCR_PROPS_HID_REPORT USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
|
||||||
|
# else
|
||||||
|
# define USB_CFG_DESCR_PROPS_HID_REPORT 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef USB_CFG_DESCR_PROPS_UNKNOWN
|
||||||
|
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------ forward declaration of descriptors ------------------- */
|
||||||
|
/* If you use external static descriptors, they must be stored in global
|
||||||
|
* arrays as declared below:
|
||||||
|
*/
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
extern
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM)
|
||||||
|
const PROGMEM
|
||||||
|
#endif
|
||||||
|
char usbDescriptorDevice[];
|
||||||
|
|
||||||
|
extern
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM)
|
||||||
|
const PROGMEM
|
||||||
|
#endif
|
||||||
|
char usbDescriptorConfiguration[];
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
extern
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM)
|
||||||
|
const PROGMEM
|
||||||
|
#endif
|
||||||
|
char usbDescriptorHidReport[];
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM)
|
||||||
|
const PROGMEM
|
||||||
|
#endif
|
||||||
|
char usbDescriptorString0[];
|
||||||
|
|
||||||
|
extern
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM)
|
||||||
|
const PROGMEM
|
||||||
|
#endif
|
||||||
|
int usbDescriptorStringVendor[];
|
||||||
|
|
||||||
|
extern
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM)
|
||||||
|
const PROGMEM
|
||||||
|
#endif
|
||||||
|
int usbDescriptorStringDevice[];
|
||||||
|
|
||||||
|
extern
|
||||||
|
#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM)
|
||||||
|
const PROGMEM
|
||||||
|
#endif
|
||||||
|
int usbDescriptorStringSerialNumber[];
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* ------------------------ General Purpose Macros ------------------------- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define USB_CONCAT(a, b) a ## b
|
||||||
|
#define USB_CONCAT_EXPANDED(a, b) USB_CONCAT(a, b)
|
||||||
|
|
||||||
|
#define USB_OUTPORT(name) USB_CONCAT(PORT, name)
|
||||||
|
#define USB_INPORT(name) USB_CONCAT(PIN, name)
|
||||||
|
#define USB_DDRPORT(name) USB_CONCAT(DDR, name)
|
||||||
|
/* The double-define trick above lets us concatenate strings which are
|
||||||
|
* defined by macros.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* ------------------------- Constant definitions -------------------------- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if !defined __ASSEMBLER__ && (!defined USB_CFG_VENDOR_ID || !defined USB_CFG_DEVICE_ID)
|
||||||
|
#warning "You should define USB_CFG_VENDOR_ID and USB_CFG_DEVICE_ID in usbconfig.h"
|
||||||
|
/* If the user has not defined IDs, we default to obdev's free IDs.
|
||||||
|
* See USB-IDs-for-free.txt for details.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* make sure we have a VID and PID defined, byte order is lowbyte, highbyte */
|
||||||
|
#ifndef USB_CFG_VENDOR_ID
|
||||||
|
# define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USB_CFG_DEVICE_ID
|
||||||
|
# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
|
||||||
|
# define USB_CFG_DEVICE_ID 0xdf, 0x05 /* = 0x5df = 1503, shared PID for HIDs */
|
||||||
|
# elif USB_CFG_INTERFACE_CLASS == 2
|
||||||
|
# define USB_CFG_DEVICE_ID 0xe1, 0x05 /* = 0x5e1 = 1505, shared PID for CDC Modems */
|
||||||
|
# else
|
||||||
|
# define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x5dc = 1500, obdev's free PID */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Derive Output, Input and DataDirection ports from port names */
|
||||||
|
#ifndef USB_CFG_IOPORTNAME
|
||||||
|
#error "You must define USB_CFG_IOPORTNAME in usbconfig.h, see usbconfig-prototype.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USBOUT USB_OUTPORT(USB_CFG_IOPORTNAME)
|
||||||
|
#define USB_PULLUP_OUT USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME)
|
||||||
|
#define USBIN USB_INPORT(USB_CFG_IOPORTNAME)
|
||||||
|
#define USBDDR USB_DDRPORT(USB_CFG_IOPORTNAME)
|
||||||
|
#define USB_PULLUP_DDR USB_DDRPORT(USB_CFG_PULLUP_IOPORTNAME)
|
||||||
|
|
||||||
|
#define USBMINUS USB_CFG_DMINUS_BIT
|
||||||
|
#define USBPLUS USB_CFG_DPLUS_BIT
|
||||||
|
#define USBIDLE (1<<USB_CFG_DMINUS_BIT) /* value representing J state */
|
||||||
|
#define USBMASK ((1<<USB_CFG_DPLUS_BIT) | (1<<USB_CFG_DMINUS_BIT)) /* mask for USB I/O bits */
|
||||||
|
|
||||||
|
/* defines for backward compatibility with older driver versions: */
|
||||||
|
#define USB_CFG_IOPORT USB_OUTPORT(USB_CFG_IOPORTNAME)
|
||||||
|
#ifdef USB_CFG_PULLUP_IOPORTNAME
|
||||||
|
#define USB_CFG_PULLUP_IOPORT USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USB_CFG_EP3_NUMBER /* if not defined in usbconfig.h */
|
||||||
|
#define USB_CFG_EP3_NUMBER 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */
|
||||||
|
|
||||||
|
/* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */
|
||||||
|
|
||||||
|
#ifndef USB_INTR_CFG /* allow user to override our default */
|
||||||
|
# if defined EICRA
|
||||||
|
# define USB_INTR_CFG EICRA
|
||||||
|
# else
|
||||||
|
# define USB_INTR_CFG MCUCR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef USB_INTR_CFG_SET /* allow user to override our default */
|
||||||
|
# if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK)
|
||||||
|
# define USB_INTR_CFG_SET (1 << ISC01) /* cfg for falling edge */
|
||||||
|
/* If any SOF logic is used, the interrupt must be wired to D- where
|
||||||
|
* we better trigger on falling edge
|
||||||
|
*/
|
||||||
|
# else
|
||||||
|
# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef USB_INTR_CFG_CLR /* allow user to override our default */
|
||||||
|
# define USB_INTR_CFG_CLR 0 /* no bits to clear */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USB_INTR_ENABLE /* allow user to override our default */
|
||||||
|
# if defined GIMSK
|
||||||
|
# define USB_INTR_ENABLE GIMSK
|
||||||
|
# elif defined EIMSK
|
||||||
|
# define USB_INTR_ENABLE EIMSK
|
||||||
|
# else
|
||||||
|
# define USB_INTR_ENABLE GICR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef USB_INTR_ENABLE_BIT /* allow user to override our default */
|
||||||
|
# define USB_INTR_ENABLE_BIT INT0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USB_INTR_PENDING /* allow user to override our default */
|
||||||
|
# if defined EIFR
|
||||||
|
# define USB_INTR_PENDING EIFR
|
||||||
|
# else
|
||||||
|
# define USB_INTR_PENDING GIFR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef USB_INTR_PENDING_BIT /* allow user to override our default */
|
||||||
|
# define USB_INTR_PENDING_BIT INTF0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
The defines above don't work for the following chips
|
||||||
|
at90c8534: no ISC0?, no PORTB, can't find a data sheet
|
||||||
|
at86rf401: no PORTB, no MCUCR etc, low clock rate
|
||||||
|
atmega103: no ISC0? (maybe omission in header, can't find data sheet)
|
||||||
|
atmega603: not defined in avr-libc
|
||||||
|
at43usb320, at43usb355, at76c711: have USB anyway
|
||||||
|
at94k: is different...
|
||||||
|
|
||||||
|
at90s1200, attiny11, attiny12, attiny15, attiny28: these have no RAM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* ----------------- USB Specification Constants and Types ----------------- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* USB Token values */
|
||||||
|
#define USBPID_SETUP 0x2d
|
||||||
|
#define USBPID_OUT 0xe1
|
||||||
|
#define USBPID_IN 0x69
|
||||||
|
#define USBPID_DATA0 0xc3
|
||||||
|
#define USBPID_DATA1 0x4b
|
||||||
|
|
||||||
|
#define USBPID_ACK 0xd2
|
||||||
|
#define USBPID_NAK 0x5a
|
||||||
|
#define USBPID_STALL 0x1e
|
||||||
|
|
||||||
|
#ifndef USB_INITIAL_DATATOKEN
|
||||||
|
#define USB_INITIAL_DATATOKEN USBPID_DATA1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
typedef struct usbTxStatus{
|
||||||
|
volatile uchar len;
|
||||||
|
uchar buffer[USB_BUFSIZE];
|
||||||
|
}usbTxStatus_t;
|
||||||
|
|
||||||
|
extern usbTxStatus_t usbTxStatus1, usbTxStatus3;
|
||||||
|
#define usbTxLen1 usbTxStatus1.len
|
||||||
|
#define usbTxBuf1 usbTxStatus1.buffer
|
||||||
|
#define usbTxLen3 usbTxStatus3.len
|
||||||
|
#define usbTxBuf3 usbTxStatus3.buffer
|
||||||
|
|
||||||
|
|
||||||
|
typedef union usbWord{
|
||||||
|
unsigned word;
|
||||||
|
uchar bytes[2];
|
||||||
|
}usbWord_t;
|
||||||
|
|
||||||
|
typedef struct usbRequest{
|
||||||
|
uchar bmRequestType;
|
||||||
|
uchar bRequest;
|
||||||
|
usbWord_t wValue;
|
||||||
|
usbWord_t wIndex;
|
||||||
|
usbWord_t wLength;
|
||||||
|
}usbRequest_t;
|
||||||
|
/* This structure matches the 8 byte setup request */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* bmRequestType field in USB setup:
|
||||||
|
* d t t r r r r r, where
|
||||||
|
* d ..... direction: 0=host->device, 1=device->host
|
||||||
|
* t ..... type: 0=standard, 1=class, 2=vendor, 3=reserved
|
||||||
|
* r ..... recipient: 0=device, 1=interface, 2=endpoint, 3=other
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* USB setup recipient values */
|
||||||
|
#define USBRQ_RCPT_MASK 0x1f
|
||||||
|
#define USBRQ_RCPT_DEVICE 0
|
||||||
|
#define USBRQ_RCPT_INTERFACE 1
|
||||||
|
#define USBRQ_RCPT_ENDPOINT 2
|
||||||
|
|
||||||
|
/* USB request type values */
|
||||||
|
#define USBRQ_TYPE_MASK 0x60
|
||||||
|
#define USBRQ_TYPE_STANDARD (0<<5)
|
||||||
|
#define USBRQ_TYPE_CLASS (1<<5)
|
||||||
|
#define USBRQ_TYPE_VENDOR (2<<5)
|
||||||
|
|
||||||
|
/* USB direction values: */
|
||||||
|
#define USBRQ_DIR_MASK 0x80
|
||||||
|
#define USBRQ_DIR_HOST_TO_DEVICE (0<<7)
|
||||||
|
#define USBRQ_DIR_DEVICE_TO_HOST (1<<7)
|
||||||
|
|
||||||
|
/* USB Standard Requests */
|
||||||
|
#define USBRQ_GET_STATUS 0
|
||||||
|
#define USBRQ_CLEAR_FEATURE 1
|
||||||
|
#define USBRQ_SET_FEATURE 3
|
||||||
|
#define USBRQ_SET_ADDRESS 5
|
||||||
|
#define USBRQ_GET_DESCRIPTOR 6
|
||||||
|
#define USBRQ_SET_DESCRIPTOR 7
|
||||||
|
#define USBRQ_GET_CONFIGURATION 8
|
||||||
|
#define USBRQ_SET_CONFIGURATION 9
|
||||||
|
#define USBRQ_GET_INTERFACE 10
|
||||||
|
#define USBRQ_SET_INTERFACE 11
|
||||||
|
#define USBRQ_SYNCH_FRAME 12
|
||||||
|
|
||||||
|
/* USB descriptor constants */
|
||||||
|
#define USBDESCR_DEVICE 1
|
||||||
|
#define USBDESCR_CONFIG 2
|
||||||
|
#define USBDESCR_STRING 3
|
||||||
|
#define USBDESCR_INTERFACE 4
|
||||||
|
#define USBDESCR_ENDPOINT 5
|
||||||
|
#define USBDESCR_HID 0x21
|
||||||
|
#define USBDESCR_HID_REPORT 0x22
|
||||||
|
#define USBDESCR_HID_PHYS 0x23
|
||||||
|
|
||||||
|
//#define USBATTR_BUSPOWER 0x80 // USB 1.1 does not define this value any more
|
||||||
|
#define USBATTR_SELFPOWER 0x40
|
||||||
|
#define USBATTR_REMOTEWAKE 0x20
|
||||||
|
|
||||||
|
/* USB HID Requests */
|
||||||
|
#define USBRQ_HID_GET_REPORT 0x01
|
||||||
|
#define USBRQ_HID_GET_IDLE 0x02
|
||||||
|
#define USBRQ_HID_GET_PROTOCOL 0x03
|
||||||
|
#define USBRQ_HID_SET_REPORT 0x09
|
||||||
|
#define USBRQ_HID_SET_IDLE 0x0a
|
||||||
|
#define USBRQ_HID_SET_PROTOCOL 0x0b
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#endif /* __usbdrv_h_included__ */
|
393
hardware/digistump/avr/libraries/DigiCDC/usbdrvasm.S
Normal file
393
hardware/digistump/avr/libraries/DigiCDC/usbdrvasm.S
Normal file
@ -0,0 +1,393 @@
|
|||||||
|
/* Name: usbdrvasm.S
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2007-06-13
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* Revision: $Id: usbdrvasm.S 785 2010-05-30 17:57:07Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This module is the assembler part of the USB driver. This file contains
|
||||||
|
general code (preprocessor acrobatics and CRC computation) and then includes
|
||||||
|
the file appropriate for the given clock rate.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
|
||||||
|
#include "usbportability.h"
|
||||||
|
#include "usbdrv.h" /* for common defs */
|
||||||
|
|
||||||
|
/* register names */
|
||||||
|
#define x1 r16
|
||||||
|
#define x2 r17
|
||||||
|
#define shift r18
|
||||||
|
#define cnt r19
|
||||||
|
#define x3 r20
|
||||||
|
#define x4 r21
|
||||||
|
#define x5 r22
|
||||||
|
#define bitcnt x5
|
||||||
|
#define phase x4
|
||||||
|
#define leap x4
|
||||||
|
|
||||||
|
/* Some assembler dependent definitions and declarations: */
|
||||||
|
|
||||||
|
#ifdef __IAR_SYSTEMS_ASM__
|
||||||
|
extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
|
||||||
|
extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
|
||||||
|
extern usbTxBuf, usbTxStatus1, usbTxStatus3
|
||||||
|
# if USB_COUNT_SOF
|
||||||
|
extern usbSofCount
|
||||||
|
# endif
|
||||||
|
public usbCrc16
|
||||||
|
public usbCrc16Append
|
||||||
|
|
||||||
|
COMMON INTVEC
|
||||||
|
# ifndef USB_INTR_VECTOR
|
||||||
|
ORG INT0_vect
|
||||||
|
# else /* USB_INTR_VECTOR */
|
||||||
|
ORG USB_INTR_VECTOR
|
||||||
|
# undef USB_INTR_VECTOR
|
||||||
|
# endif /* USB_INTR_VECTOR */
|
||||||
|
# define USB_INTR_VECTOR usbInterruptHandler
|
||||||
|
rjmp USB_INTR_VECTOR
|
||||||
|
RSEG CODE
|
||||||
|
|
||||||
|
#else /* __IAR_SYSTEMS_ASM__ */
|
||||||
|
|
||||||
|
# ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
|
||||||
|
# ifdef INT0_vect
|
||||||
|
# define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector
|
||||||
|
# else
|
||||||
|
# define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
.text
|
||||||
|
.global USB_INTR_VECTOR
|
||||||
|
.type USB_INTR_VECTOR, @function
|
||||||
|
.global usbCrc16
|
||||||
|
.global usbCrc16Append
|
||||||
|
#endif /* __IAR_SYSTEMS_ASM__ */
|
||||||
|
|
||||||
|
|
||||||
|
#if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */
|
||||||
|
# define USB_LOAD_PENDING(reg) in reg, USB_INTR_PENDING
|
||||||
|
# define USB_STORE_PENDING(reg) out USB_INTR_PENDING, reg
|
||||||
|
#else /* It's a memory address, use lds and sts */
|
||||||
|
# define USB_LOAD_PENDING(reg) lds reg, USB_INTR_PENDING
|
||||||
|
# define USB_STORE_PENDING(reg) sts USB_INTR_PENDING, reg
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define usbTxLen1 usbTxStatus1
|
||||||
|
#define usbTxBuf1 (usbTxStatus1 + 1)
|
||||||
|
#define usbTxLen3 usbTxStatus3
|
||||||
|
#define usbTxBuf3 (usbTxStatus3 + 1)
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Utility functions
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __IAR_SYSTEMS_ASM__
|
||||||
|
/* Register assignments for usbCrc16 on IAR cc */
|
||||||
|
/* Calling conventions on IAR:
|
||||||
|
* First parameter passed in r16/r17, second in r18/r19 and so on.
|
||||||
|
* Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
|
||||||
|
* Result is passed in r16/r17
|
||||||
|
* In case of the "tiny" memory model, pointers are only 8 bit with no
|
||||||
|
* padding. We therefore pass argument 1 as "16 bit unsigned".
|
||||||
|
*/
|
||||||
|
RTMODEL "__rt_version", "3"
|
||||||
|
/* The line above will generate an error if cc calling conventions change.
|
||||||
|
* The value "3" above is valid for IAR 4.10B/W32
|
||||||
|
*/
|
||||||
|
# define argLen r18 /* argument 2 */
|
||||||
|
# define argPtrL r16 /* argument 1 */
|
||||||
|
# define argPtrH r17 /* argument 1 */
|
||||||
|
|
||||||
|
# define resCrcL r16 /* result */
|
||||||
|
# define resCrcH r17 /* result */
|
||||||
|
|
||||||
|
# define ptrL ZL
|
||||||
|
# define ptrH ZH
|
||||||
|
# define ptr Z
|
||||||
|
# define byte r22
|
||||||
|
# define bitCnt r19
|
||||||
|
# define polyL r20
|
||||||
|
# define polyH r21
|
||||||
|
# define scratch r23
|
||||||
|
|
||||||
|
#else /* __IAR_SYSTEMS_ASM__ */
|
||||||
|
/* Register assignments for usbCrc16 on gcc */
|
||||||
|
/* Calling conventions on gcc:
|
||||||
|
* First parameter passed in r24/r25, second in r22/23 and so on.
|
||||||
|
* Callee must preserve r1-r17, r28/r29
|
||||||
|
* Result is passed in r24/r25
|
||||||
|
*/
|
||||||
|
# define argLen r22 /* argument 2 */
|
||||||
|
# define argPtrL r24 /* argument 1 */
|
||||||
|
# define argPtrH r25 /* argument 1 */
|
||||||
|
|
||||||
|
# define resCrcL r24 /* result */
|
||||||
|
# define resCrcH r25 /* result */
|
||||||
|
|
||||||
|
# define ptrL XL
|
||||||
|
# define ptrH XH
|
||||||
|
# define ptr x
|
||||||
|
# define byte r18
|
||||||
|
# define bitCnt r19
|
||||||
|
# define polyL r20
|
||||||
|
# define polyH r21
|
||||||
|
# define scratch r23
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_USE_FAST_CRC
|
||||||
|
|
||||||
|
; This implementation is faster, but has bigger code size
|
||||||
|
; Thanks to Slawomir Fras (BoskiDialer) for this code!
|
||||||
|
; It implements the following C pseudo-code:
|
||||||
|
; unsigned table(unsigned char x)
|
||||||
|
; {
|
||||||
|
; unsigned value;
|
||||||
|
;
|
||||||
|
; value = (unsigned)x << 6;
|
||||||
|
; value ^= (unsigned)x << 7;
|
||||||
|
; if(parity(x))
|
||||||
|
; value ^= 0xc001;
|
||||||
|
; return value;
|
||||||
|
; }
|
||||||
|
; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
|
||||||
|
; {
|
||||||
|
; unsigned crc = 0xffff;
|
||||||
|
;
|
||||||
|
; while(argLen--)
|
||||||
|
; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
|
||||||
|
; return ~crc;
|
||||||
|
; }
|
||||||
|
|
||||||
|
; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
|
||||||
|
; argPtr r24+25 / r16+r17
|
||||||
|
; argLen r22 / r18
|
||||||
|
; temp variables:
|
||||||
|
; byte r18 / r22
|
||||||
|
; scratch r23
|
||||||
|
; resCrc r24+r25 / r16+r17
|
||||||
|
; ptr X / Z
|
||||||
|
usbCrc16:
|
||||||
|
mov ptrL, argPtrL
|
||||||
|
mov ptrH, argPtrH
|
||||||
|
ldi resCrcL, 0xFF
|
||||||
|
ldi resCrcH, 0xFF
|
||||||
|
rjmp usbCrc16LoopTest
|
||||||
|
usbCrc16ByteLoop:
|
||||||
|
ld byte, ptr+
|
||||||
|
eor resCrcL, byte ; resCrcL is now 'x' in table()
|
||||||
|
mov byte, resCrcL ; compute parity of 'x'
|
||||||
|
swap byte
|
||||||
|
eor byte, resCrcL
|
||||||
|
mov scratch, byte
|
||||||
|
lsr byte
|
||||||
|
lsr byte
|
||||||
|
eor byte, scratch
|
||||||
|
inc byte
|
||||||
|
lsr byte
|
||||||
|
andi byte, 1 ; byte is now parity(x)
|
||||||
|
mov scratch, resCrcL
|
||||||
|
mov resCrcL, resCrcH
|
||||||
|
eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
|
||||||
|
neg byte
|
||||||
|
andi byte, 0xc0
|
||||||
|
mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
|
||||||
|
clr byte
|
||||||
|
lsr scratch
|
||||||
|
ror byte
|
||||||
|
eor resCrcH, scratch
|
||||||
|
eor resCrcL, byte
|
||||||
|
lsr scratch
|
||||||
|
ror byte
|
||||||
|
eor resCrcH, scratch
|
||||||
|
eor resCrcL, byte
|
||||||
|
usbCrc16LoopTest:
|
||||||
|
subi argLen, 1
|
||||||
|
brsh usbCrc16ByteLoop
|
||||||
|
com resCrcL
|
||||||
|
com resCrcH
|
||||||
|
ret
|
||||||
|
|
||||||
|
#else /* USB_USE_FAST_CRC */
|
||||||
|
|
||||||
|
; This implementation is slower, but has less code size
|
||||||
|
;
|
||||||
|
; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
|
||||||
|
; argPtr r24+25 / r16+r17
|
||||||
|
; argLen r22 / r18
|
||||||
|
; temp variables:
|
||||||
|
; byte r18 / r22
|
||||||
|
; bitCnt r19
|
||||||
|
; poly r20+r21
|
||||||
|
; scratch r23
|
||||||
|
; resCrc r24+r25 / r16+r17
|
||||||
|
; ptr X / Z
|
||||||
|
usbCrc16:
|
||||||
|
mov ptrL, argPtrL
|
||||||
|
mov ptrH, argPtrH
|
||||||
|
ldi resCrcL, 0
|
||||||
|
ldi resCrcH, 0
|
||||||
|
ldi polyL, lo8(0xa001)
|
||||||
|
ldi polyH, hi8(0xa001)
|
||||||
|
com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set
|
||||||
|
ldi bitCnt, 0 ; loop counter with starnd condition = end condition
|
||||||
|
rjmp usbCrcLoopEntry
|
||||||
|
usbCrcByteLoop:
|
||||||
|
ld byte, ptr+
|
||||||
|
eor resCrcL, byte
|
||||||
|
usbCrcBitLoop:
|
||||||
|
ror resCrcH ; carry is always set here (see brcs jumps to here)
|
||||||
|
ror resCrcL
|
||||||
|
brcs usbCrcNoXor
|
||||||
|
eor resCrcL, polyL
|
||||||
|
eor resCrcH, polyH
|
||||||
|
usbCrcNoXor:
|
||||||
|
subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
|
||||||
|
brcs usbCrcBitLoop
|
||||||
|
usbCrcLoopEntry:
|
||||||
|
subi argLen, -1
|
||||||
|
brcs usbCrcByteLoop
|
||||||
|
usbCrcReady:
|
||||||
|
ret
|
||||||
|
; Thanks to Reimar Doeffinger for optimizing this CRC routine!
|
||||||
|
|
||||||
|
#endif /* USB_USE_FAST_CRC */
|
||||||
|
|
||||||
|
; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
|
||||||
|
usbCrc16Append:
|
||||||
|
rcall usbCrc16
|
||||||
|
st ptr+, resCrcL
|
||||||
|
st ptr+, resCrcH
|
||||||
|
ret
|
||||||
|
|
||||||
|
#undef argLen
|
||||||
|
#undef argPtrL
|
||||||
|
#undef argPtrH
|
||||||
|
#undef resCrcL
|
||||||
|
#undef resCrcH
|
||||||
|
#undef ptrL
|
||||||
|
#undef ptrH
|
||||||
|
#undef ptr
|
||||||
|
#undef byte
|
||||||
|
#undef bitCnt
|
||||||
|
#undef polyL
|
||||||
|
#undef polyH
|
||||||
|
#undef scratch
|
||||||
|
|
||||||
|
|
||||||
|
#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
|
||||||
|
#ifdef __IAR_SYSTEMS_ASM__
|
||||||
|
/* Register assignments for usbMeasureFrameLength on IAR cc */
|
||||||
|
/* Calling conventions on IAR:
|
||||||
|
* First parameter passed in r16/r17, second in r18/r19 and so on.
|
||||||
|
* Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
|
||||||
|
* Result is passed in r16/r17
|
||||||
|
* In case of the "tiny" memory model, pointers are only 8 bit with no
|
||||||
|
* padding. We therefore pass argument 1 as "16 bit unsigned".
|
||||||
|
*/
|
||||||
|
# define resL r16
|
||||||
|
# define resH r17
|
||||||
|
# define cnt16L r30
|
||||||
|
# define cnt16H r31
|
||||||
|
# define cntH r18
|
||||||
|
|
||||||
|
#else /* __IAR_SYSTEMS_ASM__ */
|
||||||
|
/* Register assignments for usbMeasureFrameLength on gcc */
|
||||||
|
/* Calling conventions on gcc:
|
||||||
|
* First parameter passed in r24/r25, second in r22/23 and so on.
|
||||||
|
* Callee must preserve r1-r17, r28/r29
|
||||||
|
* Result is passed in r24/r25
|
||||||
|
*/
|
||||||
|
# define resL r24
|
||||||
|
# define resH r25
|
||||||
|
# define cnt16L r24
|
||||||
|
# define cnt16H r25
|
||||||
|
# define cntH r26
|
||||||
|
#endif
|
||||||
|
# define cnt16 cnt16L
|
||||||
|
|
||||||
|
; extern unsigned usbMeasurePacketLength(void);
|
||||||
|
; returns time between two idle strobes in multiples of 7 CPU clocks
|
||||||
|
.global usbMeasureFrameLength
|
||||||
|
usbMeasureFrameLength:
|
||||||
|
ldi cntH, 6 ; wait ~ 10 ms for D- == 0
|
||||||
|
clr cnt16L
|
||||||
|
clr cnt16H
|
||||||
|
usbMFTime16:
|
||||||
|
dec cntH
|
||||||
|
breq usbMFTimeout
|
||||||
|
usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe)
|
||||||
|
sbiw cnt16, 1 ;[0] [6]
|
||||||
|
breq usbMFTime16 ;[2]
|
||||||
|
sbic USBIN, USBMINUS ;[3]
|
||||||
|
rjmp usbMFWaitStrobe ;[4]
|
||||||
|
usbMFWaitIdle: ; then wait until idle again
|
||||||
|
sbis USBIN, USBMINUS ;1 wait for D- == 1
|
||||||
|
rjmp usbMFWaitIdle ;2
|
||||||
|
ldi cnt16L, 1 ;1 represents cycles so far
|
||||||
|
clr cnt16H ;1
|
||||||
|
usbMFWaitLoop:
|
||||||
|
in cntH, USBIN ;[0] [7]
|
||||||
|
adiw cnt16, 1 ;[1]
|
||||||
|
breq usbMFTimeout ;[3]
|
||||||
|
andi cntH, USBMASK ;[4]
|
||||||
|
brne usbMFWaitLoop ;[5]
|
||||||
|
usbMFTimeout:
|
||||||
|
#if resL != cnt16L
|
||||||
|
mov resL, cnt16L
|
||||||
|
mov resH, cnt16H
|
||||||
|
#endif
|
||||||
|
ret
|
||||||
|
|
||||||
|
#undef resL
|
||||||
|
#undef resH
|
||||||
|
#undef cnt16
|
||||||
|
#undef cnt16L
|
||||||
|
#undef cnt16H
|
||||||
|
#undef cntH
|
||||||
|
|
||||||
|
#endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Now include the clock rate specific code
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef USB_CFG_CLOCK_KHZ
|
||||||
|
# ifdef F_CPU
|
||||||
|
# define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
||||||
|
# else
|
||||||
|
# error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */
|
||||||
|
# if USB_CFG_CLOCK_KHZ == 18000
|
||||||
|
# include "usbdrvasm18-crc.inc"
|
||||||
|
# else
|
||||||
|
# error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
|
||||||
|
# endif
|
||||||
|
#else /* USB_CFG_CHECK_CRC */
|
||||||
|
# if USB_CFG_CLOCK_KHZ == 12000
|
||||||
|
# include "usbdrvasm12.inc"
|
||||||
|
# elif USB_CFG_CLOCK_KHZ == 12800
|
||||||
|
# include "usbdrvasm128.inc"
|
||||||
|
# elif USB_CFG_CLOCK_KHZ == 15000
|
||||||
|
# include "usbdrvasm15.inc"
|
||||||
|
# elif USB_CFG_CLOCK_KHZ == 16000
|
||||||
|
# include "usbdrvasm16.inc"
|
||||||
|
# elif USB_CFG_CLOCK_KHZ == 16500
|
||||||
|
# include "usbdrvasm165.inc"
|
||||||
|
# elif USB_CFG_CLOCK_KHZ == 20000
|
||||||
|
# include "usbdrvasm20.inc"
|
||||||
|
# else
|
||||||
|
# error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
|
||||||
|
# endif
|
||||||
|
#endif /* USB_CFG_CHECK_CRC */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user