From c93b8ac6177d3a34f16959fe88f89eb7cb2a7516 Mon Sep 17 00:00:00 2001 From: Ivan Stefanov Date: Sat, 23 Oct 2021 17:06:54 +0300 Subject: [PATCH] Added external interrupt examples --- .../Blink_LED_Low_Level.ino | 12 - .../EXTI0_Register_Demo.ino | 33 ++ Examples/EXTI_Demo/EXTI_Demo.ino | 30 ++ Examples/Register_Blink/Register_Blink.ino | 12 + .../external_interrupt/external_interrupt.ino | 6 +- Lesson_Plans/Lesson6.txt | 52 ++- Other Useful Files/Arduino.h | 260 +++++++++++++++ Other Useful Files/delay.h | 302 ++++++++++++++++++ Other Useful Files/delay_basic.h | 113 +++++++ Other Useful Files/main.cpp | 52 +++ 10 files changed, 854 insertions(+), 18 deletions(-) delete mode 100644 Examples/Blink_LED_Low_Level/Blink_LED_Low_Level.ino create mode 100644 Examples/EXTI0_Register_Demo/EXTI0_Register_Demo.ino create mode 100644 Examples/EXTI_Demo/EXTI_Demo.ino create mode 100644 Examples/Register_Blink/Register_Blink.ino create mode 100644 Other Useful Files/Arduino.h create mode 100644 Other Useful Files/delay.h create mode 100644 Other Useful Files/delay_basic.h create mode 100644 Other Useful Files/main.cpp diff --git a/Examples/Blink_LED_Low_Level/Blink_LED_Low_Level.ino b/Examples/Blink_LED_Low_Level/Blink_LED_Low_Level.ino deleted file mode 100644 index 337f87a..0000000 --- a/Examples/Blink_LED_Low_Level/Blink_LED_Low_Level.ino +++ /dev/null @@ -1,12 +0,0 @@ -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); -} diff --git a/Examples/EXTI0_Register_Demo/EXTI0_Register_Demo.ino b/Examples/EXTI0_Register_Demo/EXTI0_Register_Demo.ino new file mode 100644 index 0000000..b5a762d --- /dev/null +++ b/Examples/EXTI0_Register_Demo/EXTI0_Register_Demo.ino @@ -0,0 +1,33 @@ +#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 +} diff --git a/Examples/EXTI_Demo/EXTI_Demo.ino b/Examples/EXTI_Demo/EXTI_Demo.ino new file mode 100644 index 0000000..6433026 --- /dev/null +++ b/Examples/EXTI_Demo/EXTI_Demo.ino @@ -0,0 +1,30 @@ +#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)); +} diff --git a/Examples/Register_Blink/Register_Blink.ino b/Examples/Register_Blink/Register_Blink.ino new file mode 100644 index 0000000..16d6a65 --- /dev/null +++ b/Examples/Register_Blink/Register_Blink.ino @@ -0,0 +1,12 @@ +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) +} diff --git a/Examples/external_interrupt/external_interrupt.ino b/Examples/external_interrupt/external_interrupt.ino index 5ea877d..3c92df4 100644 --- a/Examples/external_interrupt/external_interrupt.ino +++ b/Examples/external_interrupt/external_interrupt.ino @@ -10,9 +10,9 @@ void setup() { 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); } diff --git a/Lesson_Plans/Lesson6.txt b/Lesson_Plans/Lesson6.txt index b95412b..ed5b03e 100644 --- a/Lesson_Plans/Lesson6.txt +++ b/Lesson_Plans/Lesson6.txt @@ -3,10 +3,13 @@ Преговор Ядро Регистри на ядрото - Задача (мигащ светодиод с регистри) + Задача мигащ светодиод с регистри - 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 пример за реална програма (мигащ светодиод и четене на потенциометър) Таймери @@ -15,4 +18,47 @@ 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 diff --git a/Other Useful Files/Arduino.h b/Other Useful Files/Arduino.h new file mode 100644 index 0000000..91eeb16 --- /dev/null +++ b/Other Useful Files/Arduino.h @@ -0,0 +1,260 @@ +/* + 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 +#include +#include +#include + +#include +#include +#include + +#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 diff --git a/Other Useful Files/delay.h b/Other Useful Files/delay.h new file mode 100644 index 0000000..6313536 --- /dev/null +++ b/Other Useful Files/delay.h @@ -0,0 +1,302 @@ +/* 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 +#include +#include + +/** \file */ +/** \defgroup util_delay : Convenience functions for busy-wait delay loops + \code + #define F_CPU 1000000UL // 1 MHz + //#define F_CPU 14.7456E6 + #include + \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 . 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 must be enabled, and the delay time + must 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 " +/** \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 require it to be an + integer value. + */ +# define F_CPU 1000000UL +#endif + +#ifndef __OPTIMIZE__ +# warning "Compiler optimizations disabled; functions from won't work as designed" +#endif + +#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ + !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ + __STDC_HOSTED__ +# include +#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 freestanding environment (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 freestanding environment (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_ */ diff --git a/Other Useful Files/delay_basic.h b/Other Useful Files/delay_basic.h new file mode 100644 index 0000000..9bf1e45 --- /dev/null +++ b/Other Useful Files/delay_basic.h @@ -0,0 +1,113 @@ +/* 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 + +#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 : Basic busy-wait delay loops + \code + #include + \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_ */ diff --git a/Other Useful Files/main.cpp b/Other Useful Files/main.cpp new file mode 100644 index 0000000..434cd40 --- /dev/null +++ b/Other Useful Files/main.cpp @@ -0,0 +1,52 @@ +/* + 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 + +// 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; +} + -- 2.39.5