switch to setup for Arduino Boards Manager

This commit is contained in:
Erik Tylek Kettenburg
2015-06-23 12:42:35 -07:00
parent bc55c9bb45
commit 6ca6b114d5
3581 changed files with 93 additions and 51 deletions

View 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.
.....................................................................

View File

@@ -0,0 +1,282 @@
#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);
void pwmWrite(uint8_t, int);
void pwmConnect(uint8_t);
void pwmDisconnect(uint8_t);
void pwmReset(void);
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
#define CHANNELA 3 //TIMER1A
#define CHANNELB 4 //TIMER1B
#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

View 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

View 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

View 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;
}

View 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

View 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

View 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;
}

View 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

View 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;

View 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

View 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

View 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

View 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 );
}
}

View 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

View 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

View 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; }

View File

@@ -0,0 +1,2 @@
//For compatibility with older programs
#include "Arduino.h"

View 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;
}

View 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

View 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

View 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;
}

View 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) {};

View 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

View 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
}

View File

@@ -0,0 +1,261 @@
/*
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
}
void pwmReset()
{
cbi(TCCR1D, OC1AV);
cbi(TCCR1D, OC1AU);
cbi(TCCR1D, OC1AW);
cbi(TCCR1D, OC1AX);
cbi(TCCR1D, OC1BV);
cbi(TCCR1D, OC1BU);
cbi(TCCR1D, OC1BW);
cbi(TCCR1D, OC1BX);
}
void pwmWrite(uint8_t channel, int val)
{
if( channel == 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);
OCR1A = val; // set pwm duty
} else if( channel == 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);
OCR1B = val; // set pwm duty
}
}
void pwmConnect(uint8_t pin)
{
pinMode(pin,OUTPUT);
if(pin == 2)
sbi(TCCR1D, OC1AV);
else if(pin == 0)
sbi(TCCR1D, OC1AU);
// cbi(TCCR1D, OC1AW);//used by crystal
else if(pin == 3)
sbi(TCCR1D, OC1AX);
else if(pin == 4)
sbi(TCCR1D, OC1BV);
else if(pin == 1)
sbi(TCCR1D, OC1BU);
// cbi(TCCR1D, OC1BW);//used by crystal
// sbi(TCCR1D, OC1BX);//reset pin
}
void pwmDisconnect(uint8_t pin)
{
pinMode(pin,OUTPUT);
if(pin == 2)
cbi(TCCR1D, OC1AV);
else if(pin == 0)
cbi(TCCR1D, OC1AU);
// cbi(TCCR1D, OC1AW);//used by crystal
else if(pin == 3)
cbi(TCCR1D, OC1AX);
else if(pin == 4)
cbi(TCCR1D, OC1BV);
else if(pin == 1)
cbi(TCCR1D, OC1BU);
// cbi(TCCR1D, OC1BW);//used by crystal
// cbi(TCCR1D, OC1BX);//reset pin
}
// 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 == TIMER0A){
// connect pwm to pin 8 on timer 0, channel A
sbi(TCCR0A, COM0A1);
cbi(TCCR0A, COM0A0);
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
OCR0A = 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);
cbi(TCCR1D, OC1AU);
cbi(TCCR1D, OC1AW);
cbi(TCCR1D, OC1AX);
if(pin == 2)
sbi(TCCR1D, OC1AV);
else if(pin == 0)
sbi(TCCR1D, OC1AU);
else if(pin == 3)
sbi(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);
cbi(TCCR1D, OC1BU);
cbi(TCCR1D, OC1BW);
cbi(TCCR1D, OC1BX);
if(pin == 4)
sbi(TCCR1D, OC1BV);
else if(pin == 1)
sbi(TCCR1D, OC1BU);
OCR1B = val; // set pwm duty
} else
{
if (val < 128)
{
digitalWrite(pin, LOW);
}
else
{
digitalWrite(pin, HIGH);
}
}
}
}

View 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;
}

View 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

View 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);
}

View 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);
}
}

View File

@@ -0,0 +1,6 @@
#ifndef Arduino_h
#define Arduino_h
#include <WProgram.h>
#endif

View 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

View 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

View 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;
}
}

View 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

View 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

View 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

View 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

View 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

View 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;

View 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;

View 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;

View 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 ) { }

View 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 );
}
}

View 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

View 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

View 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

View File

@@ -0,0 +1 @@
#include "wiring.h"

View 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

View 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; }

View 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

View 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);
}

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
#include <WProgram.h>
int main(void)
{
init();
setup();
for (;;)
loop();
return 0;
}

View 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) {};

View 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

View 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<65> 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

View 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

View 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
}

View 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

View 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);
}
}
}
}

View 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;
}

View 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

View 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);
}

View 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);
}
}