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