+++ /dev/null
-void setup() {
- // put your setup code here, to run once:
- DDRB |= (1 << PB5);
-}
-
-void loop() {
- // put your main code here, to run repeatedly:
- PORTB |= (1 << PB5);
- _delay_ms(1500);
- PORTB &= ~(1 << PB5);
- _delay_ms(1500);
-}
--- /dev/null
+#define LED PB5 // LED is connected to digital pin 13
+#define BTN PD2 // Button is connected to digital pin 2
+
+void setup()
+{
+ // PB5 is OUTPUT
+ DDRB |= (1 << PB5); //0b00100000; // 0x20;
+ // PD2 is INPUT
+ DDRD &= ~(1 << BTN);
+ // PD2 PULLUP turn on
+ PORTD |= (1 << BTN);
+
+ cli(); // Disable Global Interrupts
+
+ // Set INT0 mode to FALLING
+ EICRA = 0;
+ EICRA |= (1 << ISC01);
+ // Enable INT0 interrupt
+ EIMSK = 0;
+ EIMSK |= (1 << INT0);
+
+ sei(); // Enable Global Interrupts
+}
+
+void loop()
+{
+ // Empty
+}
+
+ISR(INT0_vect)
+{
+ PORTB ^= (1 << PB5); // Toggle LED
+}
--- /dev/null
+#define LED 12
+#define BTN 2
+
+// Define interrupt flag variable - must be volatile
+//volatile uint8_t state = 1;
+
+void setup() {
+ pinMode(LED,OUTPUT);
+ pinMode(BTN,INPUT_PULLUP);
+ attachInterrupt(digitalPinToInterrupt(BTN), ISR_Task, FALLING);
+}
+
+void loop() {
+ /*
+ // Read the interrupt flag and do something
+ if(state == 1)
+ {
+ digitalWrite(LED, !digitalRead(LED));
+ delay(100);
+ state = 0;
+ }
+ */
+}
+
+// Handler for the INT0 external interrupt
+void ISR_Task() {
+ //state = 1; // Better to only set a flag so that the ISR is short and fast
+ //delay(2000); // Show that delay doesn't work
+ digitalWrite(LED, !digitalRead(LED));
+}
--- /dev/null
+void setup() {
+ DDRB |= (1 << PB5); // Set digital pin 13 (Port B Pin 5) to output
+}
+
+void loop() {
+ PORTB |= (1 << PB5); // Set digital pin 13 (Port B Pin 5) high
+ _delay_ms(500); // wait 500ms
+ PORTB &= ~(1 << PB5); // Set digital pin 13 (Port B Pin 5) low
+ _delay_ms(500); // wait 500ms
+
+ //PORTB ^= (1 << PB5); // Toggle digital pin 13 (Port B Pin 5)
+}
{
pinMode(BTN_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
- attachInterrupt(digitalPinToInterrupt(BTN_PIN), button_pressed_ISR, FALLING);
- //attachInterrupt(digitalPinToInterrupt(BTN_PIN), button_pressed_ISR, RISING);
- //attachInterrupt(digitalPinToInterrupt(BTN_PIN), button_pressed_ISR, CHANGE);
+ attachInterrupt(digitalPinToInterrupt(BTN_PIN), button_pressed_ISR, FALLING);
+ //attachInterrupt(digitalPinToInterrupt(BTN_PIN), button_pressed_ISR, RISING);
+ //attachInterrupt(digitalPinToInterrupt(BTN_PIN), button_pressed_ISR, CHANGE);
Serial.begin(9600);
}
Преговор
Ядро
Регистри на ядрото
- Задача (мигащ светодиод с регистри)
+ Задача мигащ светодиод с регистри - GitLab Repo -> Examples/Register_Blink
Прекъсвания теория
Външни прекъсвания (https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/)
- Задача (бутон да сменя състоянието на светодиод)
+ Задача бутон да сменя състоянието на светодиод - GitLab Repo -> Examples/
+ Реално приложение (веднага сменя състоянието на светодиода но извежда съобщение когато успее) -> External_interrupt
+ Прост пример за toggle на светодиод с бутон -> EXTI_Demo
+ Пример за toggle на светодиод с бутон (като EXTI_Demo но само с регистри) -> EXTI0_Register_Demo
RTuinoOS пример за context switching (https://github.com/PeterVranken/RTuinOS)
FreeRTOS пример за реална програма (мигащ светодиод и четене на потенциометър)
Таймери
Допълнително:
Как се използва ШИМ сигнал с analogWrite -> https://www.arduino.cc/en/Tutorial/Foundations/PWM
-Разликата между проене нагоре/надолу/двете -> https://www.mathworks.com/help/physmod/sps/ref/pwmgenerator.html
\ No newline at end of file
+Разликата между проене нагоре/надолу/двете -> https://www.mathworks.com/help/physmod/sps/ref/pwmgenerator.html
+Тук има документация за delay функциите(и не само) който са от самия пакет библиотеки на компилатора (avr-gcc)
+ -> https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
+
+
+Всяка ардуино програма има:
+
+//#include "Arduino.h"
+
+/*
+void main()
+{
+ init();
+ setup();
+
+ while(1)
+ {
+ loop();
+ checkUART();
+ }
+}
+*/
+
+Тези файлове може да намерите и разгледате в GitLab в папка Other Useful Files
+или направо от файловете на вашия компютър (пътищата са примерни за Windows x64 за Linux вижте в интернет къде са):
+..\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino
+..\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3\cores\arduino
+
+
+/*
+void _delay_ms(uint16_t i)
+{
+ i *= 4000;
+ for(; i > 0 ; i++){}
+}
+*/
+
+Това което ви показах в час (горното) беше опростен пример за delay() функцията показващ как тя работи,
+а истинските функции за изчакване може да намерите във файлове delay.h и delay_basic.h
+(разликата е че са частично на асемблер и има сметки за броя цикли така че да може да подавате променливи)
+в директория на Arduino IDE-то (пътищата са примерни за Windows x64 за Linux вижте в интернет къде са):
+..\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\util
+..\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5\avr\include\util
+..\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\util
\ No newline at end of file
--- /dev/null
+/*
+ Arduino.h - Main include file for the Arduino SDK
+ Copyright (c) 2005-2013 Arduino Team. 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 Arduino_h
+#define Arduino_h
+
+#include <stdlib.h>
+#include <stdbool.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
+
+void yield(void);
+
+#define HIGH 0x1
+#define LOW 0x0
+
+#define INPUT 0x0
+#define OUTPUT 0x1
+#define INPUT_PULLUP 0x2
+
+#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 EULER 2.718281828459045235360287471352
+
+#define SERIAL 0x0
+#define DISPLAY 0x1
+
+#define LSBFIRST 0
+#define MSBFIRST 1
+
+#define CHANGE 1
+#define FALLING 2
+#define RISING 3
+
+#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
+ #define DEFAULT 0
+ #define EXTERNAL 1
+ #define INTERNAL1V1 2
+ #define INTERNAL INTERNAL1V1
+#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
+ #define DEFAULT 0
+ #define EXTERNAL 4
+ #define INTERNAL1V1 8
+ #define INTERNAL INTERNAL1V1
+ #define INTERNAL2V56 9
+ #define INTERNAL2V56_EXTCAP 13
+#else
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
+#define INTERNAL1V1 2
+#define INTERNAL2V56 3
+#else
+#define INTERNAL 3
+#endif
+#define DEFAULT 1
+#define EXTERNAL 0
+#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)))
+#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
+#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) / clockCyclesPerMicrosecond() )
+#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
+
+#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 bitToggle(value, bit) ((value) ^= (1UL << (bit)))
+#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
+
+// avr-libc defines _NOP() since 1.6.2
+#ifndef _NOP
+#define _NOP() do { __asm__ volatile ("nop"); } while (0)
+#endif
+
+typedef unsigned int word;
+
+#define bit(b) (1UL << (b))
+
+typedef bool boolean;
+typedef uint8_t byte;
+
+void init(void);
+void initVariant(void);
+
+int atexit(void (*func)()) __attribute__((weak));
+
+void pinMode(uint8_t pin, uint8_t mode);
+void digitalWrite(uint8_t pin, uint8_t val);
+int digitalRead(uint8_t pin);
+int analogRead(uint8_t pin);
+void analogReference(uint8_t mode);
+void analogWrite(uint8_t pin, int val);
+
+unsigned long millis(void);
+unsigned long micros(void);
+void delay(unsigned long ms);
+void delayMicroseconds(unsigned int us);
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
+unsigned long pulseInLong(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 interruptNum, void (*userFunc)(void), int mode);
+void detachInterrupt(uint8_t interruptNum);
+
+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)
+
+// On the ATmega1280, the addresses of some of the port registers are
+// greater than 255, so we can't store them in uint8_t's.
+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_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 NOT_AN_INTERRUPT -1
+
+#ifdef ARDUINO_MAIN
+#define PA 1
+#define PB 2
+#define PC 3
+#define PD 4
+#define PE 5
+#define PF 6
+#define PG 7
+#define PH 8
+#define PJ 10
+#define PK 11
+#define PL 12
+#endif
+
+#define NOT_ON_TIMER 0
+#define TIMER0A 1
+#define TIMER0B 2
+#define TIMER1A 3
+#define TIMER1B 4
+#define TIMER1C 5
+#define TIMER2 6
+#define TIMER2A 7
+#define TIMER2B 8
+
+#define TIMER3A 9
+#define TIMER3B 10
+#define TIMER3C 11
+#define TIMER4A 12
+#define TIMER4B 13
+#define TIMER4C 14
+#define TIMER4D 15
+#define TIMER5A 16
+#define TIMER5B 17
+#define TIMER5C 18
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#ifdef __cplusplus
+#include "WCharacter.h"
+#include "WString.h"
+#include "HardwareSerial.h"
+#include "USBAPI.h"
+#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL)
+#error "Targets with both UART0 and CDC serial not supported"
+#endif
+
+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);
+unsigned long pulseInLong(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);
+
+// WMath prototypes
+long random(long);
+long random(long, long);
+void randomSeed(unsigned long);
+long map(long, long, long, long, long);
+
+#endif
+
+#include "pins_arduino.h"
+
+#endif
--- /dev/null
+/* Copyright (c) 2002, Marek Michalkiewicz
+ Copyright (c) 2004,2005,2007 Joerg Wunsch
+ Copyright (c) 2007 Florin-Viorel Petrov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE. */
+
+/* $Id$ */
+
+#ifndef _UTIL_DELAY_H_
+#define _UTIL_DELAY_H_ 1
+
+#ifndef __DOXYGEN__
+# ifndef __HAS_DELAY_CYCLES
+# define __HAS_DELAY_CYCLES 1
+# endif
+#endif /* __DOXYGEN__ */
+
+#include <inttypes.h>
+#include <util/delay_basic.h>
+#include <math.h>
+
+/** \file */
+/** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
+ \code
+ #define F_CPU 1000000UL // 1 MHz
+ //#define F_CPU 14.7456E6
+ #include <util/delay.h>
+ \endcode
+
+ \note As an alternative method, it is possible to pass the
+ F_CPU macro down to the compiler from the Makefile.
+ Obviously, in that case, no \c \#define statement should be
+ used.
+
+ The functions in this header file are wrappers around the basic
+ busy-wait functions from <util/delay_basic.h>. They are meant as
+ convenience functions where actual time values can be specified
+ rather than a number of cycles to wait for. The idea behind is
+ that compile-time constant expressions will be eliminated by
+ compiler optimization so floating-point expressions can be used
+ to calculate the number of delay cycles needed based on the CPU
+ frequency passed by the macro F_CPU.
+
+ \note In order for these functions to work as intended, compiler
+ optimizations <em>must</em> be enabled, and the delay time
+ <em>must</em> be an expression that is a known constant at
+ compile-time. If these requirements are not met, the resulting
+ delay will be much longer (and basically unpredictable), and
+ applications that otherwise do not use floating-point calculations
+ will experience severe code bloat by the floating-point library
+ routines linked into the application.
+
+ The functions available allow the specification of microsecond, and
+ millisecond delays directly, using the application-supplied macro
+ F_CPU as the CPU clock frequency (in Hertz).
+
+*/
+
+#if !defined(__DOXYGEN__)
+static __inline__ void _delay_us(double __us) __attribute__((__always_inline__));
+static __inline__ void _delay_ms(double __ms) __attribute__((__always_inline__));
+#endif
+
+#ifndef F_CPU
+/* prevent compiler error by supplying a default */
+# warning "F_CPU not defined for <util/delay.h>"
+/** \ingroup util_delay
+ \def F_CPU
+ \brief CPU frequency in Hz
+
+ The macro F_CPU specifies the CPU frequency to be considered by
+ the delay macros. This macro is normally supplied by the
+ environment (e.g. from within a project header, or the project's
+ Makefile). The value 1 MHz here is only provided as a "vanilla"
+ fallback if no such user-provided definition could be found.
+
+ In terms of the delay functions, the CPU frequency can be given as
+ a floating-point constant (e.g. 3.6864E6 for 3.6864 MHz).
+ However, the macros in <util/setbaud.h> require it to be an
+ integer value.
+ */
+# define F_CPU 1000000UL
+#endif
+
+#ifndef __OPTIMIZE__
+# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
+#endif
+
+#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
+ !defined(__DELAY_BACKWARD_COMPATIBLE__) && \
+ __STDC_HOSTED__
+# include <math.h>
+#endif
+
+/**
+ \ingroup util_delay
+
+ Perform a delay of \c __ms milliseconds, using _delay_loop_2().
+
+ The macro F_CPU is supposed to be defined to a
+ constant defining the CPU clock frequency (in Hertz).
+
+ The maximal possible delay is 262.14 ms / F_CPU in MHz.
+
+ When the user request delay which exceed the maximum possible one,
+ _delay_ms() provides a decreased resolution functionality. In this
+ mode _delay_ms() will work with a resolution of 1/10 ms, providing
+ delays up to 6.5535 seconds (independent from CPU frequency). The
+ user will not be informed about decreased resolution.
+
+ If the avr-gcc toolchain has __builtin_avr_delay_cycles()
+ support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For
+ values greater than the maximal possible delay, overflows results in
+ no delay i.e., 0ms.
+
+ Conversion of \c __ms into clock cycles may not always result in
+ integer. By default, the clock cycles rounded up to next
+ integer. This ensures that the user gets at least \c __ms
+ microseconds of delay.
+
+ Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
+ \c __DELAY_ROUND_CLOSEST__, before including this header file, the
+ algorithm can be made to round down, or round to closest integer,
+ respectively.
+
+ \note
+
+ The implementation of _delay_ms() based on
+ __builtin_avr_delay_cycles() is not backward compatible with older
+ implementations. In order to get functionality backward compatible
+ with previous versions, the macro \c "__DELAY_BACKWARD_COMPATIBLE__"
+ must be defined before including this header file. Also, the
+ backward compatible algorithm will be chosen if the code is
+ compiled in a <em>freestanding environment</em> (GCC option
+ \c -ffreestanding), as the math functions required for rounding are
+ not available to the compiler then.
+
+ */
+void
+_delay_ms(double __ms)
+{
+ double __tmp ;
+#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
+ !defined(__DELAY_BACKWARD_COMPATIBLE__) && \
+ __STDC_HOSTED__
+ uint32_t __ticks_dc;
+ extern void __builtin_avr_delay_cycles(unsigned long);
+ __tmp = ((F_CPU) / 1e3) * __ms;
+
+ #if defined(__DELAY_ROUND_DOWN__)
+ __ticks_dc = (uint32_t)fabs(__tmp);
+
+ #elif defined(__DELAY_ROUND_CLOSEST__)
+ __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
+
+ #else
+ //round up by default
+ __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
+ #endif
+
+ __builtin_avr_delay_cycles(__ticks_dc);
+
+#else
+ uint16_t __ticks;
+ __tmp = ((F_CPU) / 4e3) * __ms;
+ if (__tmp < 1.0)
+ __ticks = 1;
+ else if (__tmp > 65535)
+ {
+ // __ticks = requested delay in 1/10 ms
+ __ticks = (uint16_t) (__ms * 10.0);
+ while(__ticks)
+ {
+ // wait 1/10 ms
+ _delay_loop_2(((F_CPU) / 4e3) / 10);
+ __ticks --;
+ }
+ return;
+ }
+ else
+ __ticks = (uint16_t)__tmp;
+ _delay_loop_2(__ticks);
+#endif
+}
+
+/**
+ \ingroup util_delay
+
+ Perform a delay of \c __us microseconds, using _delay_loop_1().
+
+ The macro F_CPU is supposed to be defined to a
+ constant defining the CPU clock frequency (in Hertz).
+
+ The maximal possible delay is 768 us / F_CPU in MHz.
+
+ If the user requests a delay greater than the maximal possible one,
+ _delay_us() will automatically call _delay_ms() instead. The user
+ will not be informed about this case.
+
+ If the avr-gcc toolchain has __builtin_avr_delay_cycles()
+ support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For
+ values greater than the maximal possible delay, overflow results in
+ no delay i.e., 0us.
+
+ Conversion of \c __us into clock cycles may not always result in
+ integer. By default, the clock cycles rounded up to next
+ integer. This ensures that the user gets at least \c __us
+ microseconds of delay.
+
+ Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
+ \c __DELAY_ROUND_CLOSEST__, before including this header file, the
+ algorithm can be made to round down, or round to closest integer,
+ respectively.
+
+ \note
+
+ The implementation of _delay_ms() based on
+ __builtin_avr_delay_cycles() is not backward compatible with older
+ implementations. In order to get functionality backward compatible
+ with previous versions, the macro \c __DELAY_BACKWARD_COMPATIBLE__
+ must be defined before including this header file. Also, the
+ backward compatible algorithm will be chosen if the code is
+ compiled in a <em>freestanding environment</em> (GCC option
+ \c -ffreestanding), as the math functions required for rounding are
+ not available to the compiler then.
+
+ */
+void
+_delay_us(double __us)
+{
+ double __tmp ;
+#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
+ !defined(__DELAY_BACKWARD_COMPATIBLE__) && \
+ __STDC_HOSTED__
+ uint32_t __ticks_dc;
+ extern void __builtin_avr_delay_cycles(unsigned long);
+ __tmp = ((F_CPU) / 1e6) * __us;
+
+ #if defined(__DELAY_ROUND_DOWN__)
+ __ticks_dc = (uint32_t)fabs(__tmp);
+
+ #elif defined(__DELAY_ROUND_CLOSEST__)
+ __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
+
+ #else
+ //round up by default
+ __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
+ #endif
+
+ __builtin_avr_delay_cycles(__ticks_dc);
+
+#else
+ uint8_t __ticks;
+ double __tmp2 ;
+ __tmp = ((F_CPU) / 3e6) * __us;
+ __tmp2 = ((F_CPU) / 4e6) * __us;
+ if (__tmp < 1.0)
+ __ticks = 1;
+ else if (__tmp2 > 65535)
+ {
+ _delay_ms(__us / 1000.0);
+ }
+ else if (__tmp > 255)
+ {
+ uint16_t __ticks=(uint16_t)__tmp2;
+ _delay_loop_2(__ticks);
+ return;
+ }
+ else
+ __ticks = (uint8_t)__tmp;
+ _delay_loop_1(__ticks);
+#endif
+}
+
+
+#endif /* _UTIL_DELAY_H_ */
--- /dev/null
+/* Copyright (c) 2002, Marek Michalkiewicz
+ Copyright (c) 2007 Joerg Wunsch
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE. */
+
+/* $Id$ */
+
+#ifndef _UTIL_DELAY_BASIC_H_
+#define _UTIL_DELAY_BASIC_H_ 1
+
+#include <inttypes.h>
+
+#if !defined(__DOXYGEN__)
+static __inline__ void _delay_loop_1(uint8_t __count) __attribute__((__always_inline__));
+static __inline__ void _delay_loop_2(uint16_t __count) __attribute__((__always_inline__));
+#endif
+
+/** \file */
+/** \defgroup util_delay_basic <util/delay_basic.h>: Basic busy-wait delay loops
+ \code
+ #include <util/delay_basic.h>
+ \endcode
+
+ The functions in this header file implement simple delay loops
+ that perform a busy-waiting. They are typically used to
+ facilitate short delays in the program execution. They are
+ implemented as count-down loops with a well-known CPU cycle
+ count per loop iteration. As such, no other processing can
+ occur simultaneously. It should be kept in mind that the
+ functions described here do not disable interrupts.
+
+ In general, for long delays, the use of hardware timers is
+ much preferrable, as they free the CPU, and allow for
+ concurrent processing of other events while the timer is
+ running. However, in particular for very short delays, the
+ overhead of setting up a hardware timer is too much compared
+ to the overall delay time.
+
+ Two inline functions are provided for the actual delay algorithms.
+
+*/
+
+/** \ingroup util_delay_basic
+
+ Delay loop using an 8-bit counter \c __count, so up to 256
+ iterations are possible. (The value 256 would have to be passed
+ as 0.) The loop executes three CPU cycles per iteration, not
+ including the overhead the compiler needs to setup the counter
+ register.
+
+ Thus, at a CPU speed of 1 MHz, delays of up to 768 microseconds
+ can be achieved.
+*/
+void
+_delay_loop_1(uint8_t __count)
+{
+ __asm__ volatile (
+ "1: dec %0" "\n\t"
+ "brne 1b"
+ : "=r" (__count)
+ : "0" (__count)
+ );
+}
+
+/** \ingroup util_delay_basic
+
+ Delay loop using a 16-bit counter \c __count, so up to 65536
+ iterations are possible. (The value 65536 would have to be
+ passed as 0.) The loop executes four CPU cycles per iteration,
+ not including the overhead the compiler requires to setup the
+ counter register pair.
+
+ Thus, at a CPU speed of 1 MHz, delays of up to about 262.1
+ milliseconds can be achieved.
+ */
+void
+_delay_loop_2(uint16_t __count)
+{
+ __asm__ volatile (
+ "1: sbiw %0,1" "\n\t"
+ "brne 1b"
+ : "=w" (__count)
+ : "0" (__count)
+ );
+}
+
+#endif /* _UTIL_DELAY_BASIC_H_ */
--- /dev/null
+/*
+ main.cpp - Main loop for Arduino sketches
+ Copyright (c) 2005-2013 Arduino Team. 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
+*/
+
+#include <Arduino.h>
+
+// Declared weak in Arduino.h to allow user redefinitions.
+int atexit(void (* /*func*/ )()) { return 0; }
+
+// Weak empty variant initialization function.
+// May be redefined by variant files.
+void initVariant() __attribute__((weak));
+void initVariant() { }
+
+void setupUSB() __attribute__((weak));
+void setupUSB() { }
+
+int main(void)
+{
+ init();
+
+ initVariant();
+
+#if defined(USBCON)
+ USBDevice.attach();
+#endif
+
+ setup();
+
+ for (;;) {
+ loop();
+ if (serialEventRun) serialEventRun();
+ }
+
+ return 0;
+}
+