From c52f478bb59c6fc9969a70bd486b79adb9a0eb03 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 2 Aug 2019 19:08:10 +0300 Subject: [PATCH] add --- GyverCore/boards.txt | 10 +- GyverCore/cores/arduino/Arduino.h | 59 +-- GyverCore/cores/arduino/Tone.cpp | 647 ++----------------------- GyverCore/cores/arduino/main.cpp | 13 +- GyverCore/cores/arduino/time&init.cpp | 52 +- GyverCore/cores/arduino/uart.cpp | 36 +- GyverCore/cores/arduino/uart.h | 4 +- GyverCore/cores/arduino/wiring_pulse.c | 78 ++- GyverCore/cores/arduino/wiring_shift.c | 23 +- GyverCore/keywords.txt | 6 + README.md | 38 +- examples/advancedPWM/advancedPWM.ino | 22 + examples/memtest/memtest.ino | 28 ++ examples/parseTest/parseTest.ino | 21 + examples/printTest/printTest.ino | 37 ++ package_GyverCore_index.json | 6 +- 16 files changed, 295 insertions(+), 785 deletions(-) create mode 100644 examples/advancedPWM/advancedPWM.ino create mode 100644 examples/memtest/memtest.ino create mode 100644 examples/parseTest/parseTest.ino create mode 100644 examples/printTest/printTest.ino diff --git a/GyverCore/boards.txt b/GyverCore/boards.txt index d3fec86..81d8313 100644 --- a/GyverCore/boards.txt +++ b/GyverCore/boards.txt @@ -5,7 +5,7 @@ menu.timers=Timers ###################### -nano.name=ATmega328P based +nano.name=ATmega328/168 based nano.upload.tool=avrdude nano.upload.protocol=arduino @@ -21,10 +21,10 @@ nano.build.core=arduino ## timer0 OVF ON/OFF ## -------------------------- -nano.menu.timers.yes_millis=yes millis +nano.menu.timers.yes_millis=with millis nano.menu.timers.yes_millis.build.variant=yesmillis -nano.menu.timers.no_millis=no millis +nano.menu.timers.no_millis=without millis nano.menu.timers.no_millis.build.variant=nomillis @@ -62,7 +62,7 @@ nano.menu.cpu.atmega328old.build.mcu=atmega328p ## ATmega328P - NO bootloader ## -------------------------- -nano.menu.cpu.atmega328noBoot=ATmega328P - NO bootloader +nano.menu.cpu.atmega328noBoot=ATmega328P - without bootloader nano.menu.cpu.atmega328noBoot.upload.maximum_size=32768 nano.menu.cpu.atmega328noBoot.upload.maximum_data_size=2048 @@ -107,7 +107,7 @@ nano.menu.cpu.atmega168old.build.mcu=atmega168 ## ATmega168 - NO bootloader ## ------------------------- -nano.menu.cpu.atmega168noBoot=ATmega168 - NO bootloader +nano.menu.cpu.atmega168noBoot=ATmega168 - without bootloader nano.menu.cpu.atmega168noBoot.upload.maximum_size=16144 nano.menu.cpu.atmega168noBoot.upload.maximum_data_size=1024 diff --git a/GyverCore/cores/arduino/Arduino.h b/GyverCore/cores/arduino/Arduino.h index 0abd64e..1c61a7d 100644 --- a/GyverCore/cores/arduino/Arduino.h +++ b/GyverCore/cores/arduino/Arduino.h @@ -161,62 +161,7 @@ void detachInterrupt(uint8_t); void setup(void); void loop(void); -#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_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; - -#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 - -#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 - -#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" @@ -239,8 +184,8 @@ uint16_t makeWord(byte h, byte l); 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); +void tone(uint8_t pin , uint16_t freq, uint32_t duration = 0); +void noTone(uint8_t pin); // WMath prototypes long random(long); diff --git a/GyverCore/cores/arduino/Tone.cpp b/GyverCore/cores/arduino/Tone.cpp index 4321898..34bc28b 100644 --- a/GyverCore/cores/arduino/Tone.cpp +++ b/GyverCore/cores/arduino/Tone.cpp @@ -1,619 +1,46 @@ -/* 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 M Sproul 10/08/29 Changed #ifdefs from cpu to register -0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY -0009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62) -0010 jipp 15/04/13 added additional define check #2923 -*************************************************/ - #include -#include #include "Arduino.h" -//#include "pins_arduino.h" +/* оптимизированный вариант реализации tone */ +uint8_t tone_pin; // глобальная переменная для пина +uint32_t toggle_counter; // счетчик toggl'ов +uint32_t toggle_top; // предел счета для toggl'ов +bool willStop; // флаг позволяющий генерировать сигнал бесконечно долго -#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) -#define TCCR2A TCCR2 -#define TCCR2B TCCR2 -#define COM2A1 COM21 -#define COM2A0 COM20 -#define OCR2A OCR2 -#define TIMSK2 TIMSK -#define OCIE2A OCIE2 -#define TIMER2_COMPA_vect TIMER2_COMP_vect -#define TIMSK1 TIMSK -#endif +void tone(uint8_t pin , uint16_t freq, uint32_t duration = 0){ + tone_pin = pin; // присвоили номер пина для прерывания + willStop = duration;// если введено время генерации - будет ненулевым + toggle_top = (freq * duration)/500; // расчет кол-ва toggl'ов за указанное время генерации + TCCR2A = (1< 244){ // минимальный делитель + TCCR2B = 0x5; // по аналогии см выше + OCR2A = (62500/freq)-1; // по аналогии см выше + } + else { // средний делитель + TCCR2B = 0x6; // по аналогии см выше + OCR2A = (125000/freq)-1; // по аналогии см выше + } + toggle_counter = 0; // обнулили счетчик toggl'ов +} -// timerx_toggle_count: -// > 0 - duration specified -// = 0 - stopped -// < 0 - infinitely (until stop() method called, or new play() called) - -#if !defined(__AVR_ATmega8__) -volatile long timer0_toggle_count; -volatile uint8_t *timer0_pin_port; -volatile uint8_t timer0_pin_mask; -#endif - -volatile long timer1_toggle_count; -volatile uint8_t *timer1_pin_port; -volatile uint8_t timer1_pin_mask; -volatile long timer2_toggle_count; -volatile uint8_t *timer2_pin_port; -volatile uint8_t timer2_pin_mask; - -#if defined(TIMSK3) -volatile long timer3_toggle_count; -volatile uint8_t *timer3_pin_port; -volatile uint8_t timer3_pin_mask; -#endif - -#if defined(TIMSK4) -volatile long timer4_toggle_count; -volatile uint8_t *timer4_pin_port; -volatile uint8_t timer4_pin_mask; -#endif - -#if defined(TIMSK5) -volatile long timer5_toggle_count; -volatile uint8_t *timer5_pin_port; -volatile uint8_t timer5_pin_mask; -#endif - - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; - -#elif defined(__AVR_ATmega8__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#elif defined(__AVR_ATmega32U4__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER3 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#else - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -// Leave timer 0 to last. -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; - -#endif - - - -static int8_t toneBegin(uint8_t _pin) -{ - int8_t _timer = -1; - - // if we're already using the pin, the timer should be configured. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == _pin) { - return pgm_read_byte(tone_pin_to_timer_PGM + i); - } - } - - // search for an unused timer. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == 255) { - tone_pins[i] = _pin; - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - break; - } - } - - if (_timer != -1) - { - // Set timer specific stuff - // All timers in CTC mode - // 8 bit timers will require changing prescalar values, - // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar - switch (_timer) - { - #if defined(TCCR0A) && defined(TCCR0B) && defined(WGM01) - case 0: - // 8 bit timer - TCCR0A = 0; - TCCR0B = 0; - bitWrite(TCCR0A, WGM01, 1); - bitWrite(TCCR0B, CS00, 1); - timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer0_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12) - case 1: - // 16 bit timer - TCCR1A = 0; - TCCR1B = 0; - bitWrite(TCCR1B, WGM12, 1); - bitWrite(TCCR1B, CS10, 1); - timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer1_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR2A) && defined(TCCR2B) - case 2: - // 8 bit timer - TCCR2A = 0; - TCCR2B = 0; - bitWrite(TCCR2A, WGM21, 1); - bitWrite(TCCR2B, CS20, 1); - timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer2_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3) - case 3: - // 16 bit timer - TCCR3A = 0; - TCCR3B = 0; - bitWrite(TCCR3B, WGM32, 1); - bitWrite(TCCR3B, CS30, 1); - timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer3_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4) - case 4: - // 16 bit timer - TCCR4A = 0; - TCCR4B = 0; - #if defined(WGM42) - bitWrite(TCCR4B, WGM42, 1); - #elif defined(CS43) - // TODO this may not be correct - // atmega32u4 - bitWrite(TCCR4B, CS43, 1); - #endif - bitWrite(TCCR4B, CS40, 1); - timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer4_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5) - case 5: - // 16 bit timer - TCCR5A = 0; - TCCR5B = 0; - bitWrite(TCCR5B, WGM52, 1); - bitWrite(TCCR5B, CS50, 1); - timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer5_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - } - } - - return _timer; +void noTone(uint8_t pin){ // если вызван noTone + digitalWrite(pin,0);// устанавливаем 0 на выходе + TIMSK2 &=~ (1<= 0) - { - // Set the pinMode as OUTPUT - pinMode(_pin, OUTPUT); - - // if we are using an 8 bit timer, scan through prescalars to find the best fit - if (_timer == 0 || _timer == 2) - { - ocr = F_CPU / frequency / 2 - 1; - prescalarbits = 0b001; // ck/1: same for both timers - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 8 - 1; - prescalarbits = 0b010; // ck/8: same for both timers - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 32 - 1; - prescalarbits = 0b011; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = _timer == 0 ? 0b011 : 0b100; - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 128 - 1; - prescalarbits = 0b101; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 256 - 1; - prescalarbits = _timer == 0 ? 0b100 : 0b110; - if (ocr > 255) - { - // can't do any better than /1024 - ocr = F_CPU / frequency / 2 / 1024 - 1; - prescalarbits = _timer == 0 ? 0b101 : 0b111; - } - } - } - } - -#if defined(TCCR0B) - if (_timer == 0) - { - TCCR0B = (TCCR0B & 0b11111000) | prescalarbits; - } - else -#endif -#if defined(TCCR2B) - { - TCCR2B = (TCCR2B & 0b11111000) | prescalarbits; - } -#else - { - // dummy place holder to make the above ifdefs work - } -#endif - } - else - { - // two choices for the 16 bit timers: ck/1 or ck/64 - ocr = F_CPU / frequency / 2 - 1; - - prescalarbits = 0b001; - if (ocr > 0xffff) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = 0b011; - } - - if (_timer == 1) - { -#if defined(TCCR1B) - TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; -#endif - } -#if defined(TCCR3B) - else if (_timer == 3) - TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; -#endif -#if defined(TCCR4B) - else if (_timer == 4) - TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; -#endif -#if defined(TCCR5B) - else if (_timer == 5) - TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; -#endif - - } - - - // Calculate the toggle count - if (duration > 0) - { - toggle_count = 2 * frequency * duration / 1000; - } - else - { - toggle_count = -1; - } - - // Set the OCR for the given timer, - // set the toggle count, - // then turn on the interrupts - switch (_timer) - { - -#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A) - case 0: - OCR0A = ocr; - timer0_toggle_count = toggle_count; - bitWrite(TIMSK0, OCIE0A, 1); - break; -#endif - - case 1: -#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A) - OCR1A = ocr; - timer1_toggle_count = toggle_count; - bitWrite(TIMSK1, OCIE1A, 1); -#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A) - // this combination is for at least the ATmega32 - OCR1A = ocr; - timer1_toggle_count = toggle_count; - bitWrite(TIMSK, OCIE1A, 1); -#endif - break; - -#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A) - case 2: - OCR2A = ocr; - timer2_toggle_count = toggle_count; - bitWrite(TIMSK2, OCIE2A, 1); - break; -#endif - -#if defined(OCR3A) && defined(TIMSK3) && defined(OCIE3A) - case 3: - OCR3A = ocr; - timer3_toggle_count = toggle_count; - bitWrite(TIMSK3, OCIE3A, 1); - break; -#endif - -#if defined(OCR4A) && defined(TIMSK4) && defined(OCIE4A) - case 4: - OCR4A = ocr; - timer4_toggle_count = toggle_count; - bitWrite(TIMSK4, OCIE4A, 1); - break; -#endif - -#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A) - case 5: - OCR5A = ocr; - timer5_toggle_count = toggle_count; - bitWrite(TIMSK5, OCIE5A, 1); - break; -#endif - - } - } +ISR(TIMER2_COMPA_vect){ // прерывание генерации + if(toggle_counter < toggle_top || !willStop ){ // если количество toggl'ов не достигло предела или процесс бесконечен - генерация + digitalToggle(tone_pin); // иневертируем состоние на ноге + toggle_counter++; // икремент счетчика + } } - -// XXX: this function only works properly for timer 2 (the only one we use -// currently). for the others, it should end the tone, but won't restore -// proper PWM functionality for the timer. -void disableTimer(uint8_t _timer) -{ - switch (_timer) - { - case 0: - #if defined(TIMSK0) - TIMSK0 = 0; - #elif defined(TIMSK) - TIMSK = 0; // atmega32 - #endif - break; - -#if defined(TIMSK1) && defined(OCIE1A) - case 1: - bitWrite(TIMSK1, OCIE1A, 0); - break; -#endif - - case 2: - #if defined(TIMSK2) && defined(OCIE2A) - bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt - #endif - #if defined(TCCR2A) && defined(WGM20) - TCCR2A = (1 << WGM20); - #endif - #if defined(TCCR2B) && defined(CS22) - TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); - #endif - #if defined(OCR2A) - OCR2A = 0; - #endif - break; - -#if defined(TIMSK3) && defined(OCIE3A) - case 3: - bitWrite(TIMSK3, OCIE3A, 0); - break; -#endif - -#if defined(TIMSK4) && defined(OCIE4A) - case 4: - bitWrite(TIMSK4, OCIE4A, 0); - break; -#endif - -#if defined(TIMSK5) && defined(OCIE5A) - case 5: - bitWrite(TIMSK5, OCIE5A, 0); - break; -#endif - } -} - - -void noTone(uint8_t _pin) -{ - int8_t _timer = -1; - - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == _pin) { - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - tone_pins[i] = 255; - break; - } - } - - disableTimer(_timer); - - digitalWrite(_pin, 0); -} - -#ifdef USE_TIMER0 -ISR(TIMER0_COMPA_vect) -{ - if (timer0_toggle_count != 0) - { - // toggle the pin - *timer0_pin_port ^= timer0_pin_mask; - - if (timer0_toggle_count > 0) - timer0_toggle_count--; - } - else - { - disableTimer(0); - *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER1 -ISR(TIMER1_COMPA_vect) -{ - if (timer1_toggle_count != 0) - { - // toggle the pin - *timer1_pin_port ^= timer1_pin_mask; - - if (timer1_toggle_count > 0) - timer1_toggle_count--; - } - else - { - disableTimer(1); - *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER2 -ISR(TIMER2_COMPA_vect) -{ - - if (timer2_toggle_count != 0) - { - // toggle the pin - *timer2_pin_port ^= timer2_pin_mask; - - if (timer2_toggle_count > 0) - timer2_toggle_count--; - } - else - { - // need to call noTone() so that the tone_pins[] entry is reset, so the - // timer gets initialized next time we call tone(). - // XXX: this assumes timer 2 is always the first one used. - noTone(tone_pins[0]); -// disableTimer(2); -// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER3 -ISR(TIMER3_COMPA_vect) -{ - if (timer3_toggle_count != 0) - { - // toggle the pin - *timer3_pin_port ^= timer3_pin_mask; - - if (timer3_toggle_count > 0) - timer3_toggle_count--; - } - else - { - disableTimer(3); - *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER4 -ISR(TIMER4_COMPA_vect) -{ - if (timer4_toggle_count != 0) - { - // toggle the pin - *timer4_pin_port ^= timer4_pin_mask; - - if (timer4_toggle_count > 0) - timer4_toggle_count--; - } - else - { - disableTimer(4); - *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER5 -ISR(TIMER5_COMPA_vect) -{ - if (timer5_toggle_count != 0) - { - // toggle the pin - *timer5_pin_port ^= timer5_pin_mask; - - if (timer5_toggle_count > 0) - timer5_toggle_count--; - } - else - { - disableTimer(5); - *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop - } -} -#endif diff --git a/GyverCore/cores/arduino/main.cpp b/GyverCore/cores/arduino/main.cpp index 9902b0b..d03b268 100644 --- a/GyverCore/cores/arduino/main.cpp +++ b/GyverCore/cores/arduino/main.cpp @@ -1,12 +1,13 @@ +/* Главный цикл программы */ #include int main(void) { - WDTCSR = 0; // wdt disable - init(); - setup(); - while (1) { - loop(); - if (serialEventRun) serialEventRun(); + WDTCSR = 0; // Первым делом отключаем ватчдог + init(); // инициализация таймеров и ацп + setup(); // функция setup + while (1) { // бесконечный цикл + loop(); // функция loop + if (serialEventRun) serialEventRun(); // обслуживание serial } return 0; } diff --git a/GyverCore/cores/arduino/time&init.cpp b/GyverCore/cores/arduino/time&init.cpp index 7fcc3cb..a8ce7f4 100644 --- a/GyverCore/cores/arduino/time&init.cpp +++ b/GyverCore/cores/arduino/time&init.cpp @@ -1,6 +1,6 @@ #include "Arduino.h" #include "timeControl.h" - +/* функции времени и инициализация таймеров , АЦП*/ #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) // 1024 #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) // 1 #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) // 3 @@ -10,7 +10,7 @@ volatile unsigned long timer0_overflow_count = 0; volatile unsigned long timer0_millis = 0; static unsigned char timer0_fract = 0; -#ifdef MILLIS_TMRS +#ifdef MILLIS_TMRS // переключатель, отключающий millis(), освобождающий вектор прерывания ISR(TIMER0_OVF_vect) { timer0_millis++; @@ -24,20 +24,20 @@ ISR(TIMER0_OVF_vect) #endif unsigned long millis() { - cli(); - unsigned long m = timer0_millis; - sei(); - return m; + cli(); // остановить счет + unsigned long m = timer0_millis; // перехватить значение + sei(); // продолжить счет + return m; // вернуть миллисекунды } unsigned long micros() { - cli(); - unsigned long m = timer0_overflow_count; - uint8_t t = TCNT0; - if ((TIFR0 & _BV(TOV0)) && (t < 255)) + cli(); // остановить прерывания + unsigned long m = timer0_overflow_count; // счет переполнений + uint8_t t = TCNT0; // считать содержимое счетного регистра + if ((TIFR0 & _BV(TOV0)) && (t < 255)) //инкремент по переполнению m++; - sei(); - return (long)(((m << 8) + t) * 4); + sei(); // продолжить счет + return (long)(((m << 8) + t) * 4); // вернуть микросекунды } /* @@ -77,11 +77,11 @@ void delayMicroseconds(unsigned int us) */ -void delay(unsigned long ms) +void delay(unsigned long ms) { - uint32_t start = micros(); + uint32_t start = micros(); // запомнили время старта - while (ms > 0) { + while (ms > 0) { // ведем отсчет yield(); while ( ms > 0 && (micros() - start) >= 1000) { ms--; @@ -91,15 +91,13 @@ void delay(unsigned long ms) } -void delayMicroseconds(unsigned int us) +void delayMicroseconds(unsigned int us) // работает на счете тиков { - #if F_CPU >= 16000000L if (us <= 1) return; // = 3 cycles, (4 when true) us <<= 2; // x4 us, = 4 cycles us -= 5; #endif - // busy wait __asm__ __volatile__ ( "1: sbiw %0,1" "\n\t" // 2 cycles @@ -109,24 +107,24 @@ void delayMicroseconds(unsigned int us) } -void init() +void init() // функция инициализации { -cli(); +cli(); /* timer 0 */ TCCR0A = 0b00000011; // fast pwm 8 bit -TCCR0B = 0b00000011; // prescaler 64 -TIMSK0 |= (1<> /2 010 >> /4 011 >> /8 100 >> /16 101 >> /32 110 >> /64 111 >> /128*/ /* UART */ -UCSR0B = 0; +UCSR0B = 0; // пока не вызван Serial.begin / uartBegin выводы 0/1 свободны для работы. sei(); } diff --git a/GyverCore/cores/arduino/uart.cpp b/GyverCore/cores/arduino/uart.cpp index a241785..4ee62c7 100644 --- a/GyverCore/cores/arduino/uart.cpp +++ b/GyverCore/cores/arduino/uart.cpp @@ -1,46 +1,48 @@ #include "uart.h" +/* Реализация облегченного Serial от AlexGyver & Egor 'Nich1con' Zaharov*/ // ===== INIT ===== -void uartBegin(uint32_t baudrate){ - uint16_t speed = (2000000/baudrate)-1; - UBRR0H = highByte(speed); +void uartBegin(uint32_t baudrate){ // инициализация uart + uint16_t speed = (2000000/baudrate)-1; // расчет baudrate + UBRR0H = highByte(speed); // установка baudrate UBRR0L = lowByte(speed); - UCSR0A = (1 << U2X0); - UCSR0B = ((1< Плата > GyverCore > ATmega328p based** +- Выбери плату в **Инструменты > Плата > GyverCore > ATmega328/168 based** - Выбери в **CPU & BOOT** нужный вариант загрузчика -- Готово +- Готово! +- *Примечание*: файлы ядра находятся по пути *C:\Users\Username\AppData\Local\Arduino15\packages\GyverCore\hardware\avr\1.0.0\* -# Изменения -## Облегчено и ускорено +## Изменения +### Облегчено и ускорено Время выполнения функций, мкс Функция | Arduino | GyverCore | Быстрее в @@ -31,7 +32,8 @@ analogWrite | 4.15 us | 1.13 us | 3.67 analogRead | 112.01 us | 5.41 us | 20.70 analogReference | 0.00 us | 0.69 us | 0.00 attachInterrupt | 1.20 us | 1.18 us | 1.02 -detachInterrupt | 0.82 us | 0.57 us | 1.44 +detachInterrupt | 0.82 us | 0.57 us | 1.44 +tone | 5.63 us | 2.40 us | 2.3 Занимаемое место, Flash, байт @@ -44,18 +46,22 @@ analogWrite | 406 | 48 | 358 analogRead | 32 | 72 | -40 analogReference | 0 | 32 | -32 attachInterrupt | 212 | 180 | 32 -detachInterrupt | 198 | 150 | 48 +detachInterrupt | 198 | 150 | 48 +tone | 1410 | 740 | 670 Serial.begin | 1028 | 166 | 862 print long | 1094 | 326 | 768 print string | 2100 | 1484 | 616 print float | 2021 | 446 | 1575 parseInt | 1030 | 214 | 816 readString | 2334 | 1594 | 740 -parseFloat | 1070 | 246 | 824 +parseFloat | 1070 | 246 | 824 -Примечание: analogRead и analogReference имеют расширенную функциональность и весят чуть больше +Примечание: analogRead и analogReference имеют расширенную функциональность и весят чуть больше +Скетч, состоящий из однократного вызова перечисленных выше функций, занимает +- Ядро Arduino: 3446 байт (11%) Flash / 217 байт (10%) SRAM +- Ядро GyverCore: 1436 байт (4%) Flash / 94 байт (4%) SRAM -## Добавлено +### Добавлено - Подсветка в коде **A0**, **A1**.. **A7** - Макрос **bitToggle**(value, bit), инвертирует состояние бита bit в байте value - Функция **digitalToggle**(pin), инвертирует состояние пина @@ -86,12 +92,16 @@ parseFloat | 1070 | 246 | 824 - **uartParseFloat()** - принять число float - **uartParsePacket(dataArray)** - принять пакет вида **$50 60 70;** в массив dataArray (смотри пример) +### Убарно +Убраны всякие сервисные файлы и прочий хлам, не относящийся к ATmega328 (wifi, USB). Ядро полностью совместимо с остальными библиотеками, ничего из стандартных функций не вырезано. + ## Дополнительно ### Настройки прошивки -- Добавлен вариант прошивки без загрузчика (во всю доступную Flash память) для прошивки через ISP -- Добавлен вариант прошивки с отключенными функциями времени (освобождает вектор **TIMER0_OVF_vect** для личного пользования) +- Смотри примеры в папке examples (в корне этого репозитория!) +- Добавлен вариант прошивки без загрузчика **ATmega 328/168 without bootloader** (во всю доступную Flash память) для прошивки через ISP +- Добавлен вариант прошивки с отключенными функциями времени **with/without millis** (освобождает вектор **TIMER0_OVF_vect** для личного пользования) -### Больше контроля! +## Больше контроля! Для большего контроля за периферией микроконтроллера рекомендую попробовать следующие наши библиотеки: - **directTimers** - полный контроль над таймерами/счётчиками ATmega328 - **directADC** - полный контроль над АЦП и компаратором ATmega328 diff --git a/examples/advancedPWM/advancedPWM.ino b/examples/advancedPWM/advancedPWM.ino new file mode 100644 index 0000000..94a537a --- /dev/null +++ b/examples/advancedPWM/advancedPWM.ino @@ -0,0 +1,22 @@ +void setup() { + setPWM_20kHz(5); // частота шим на D5 установлена на 20 кГц + // ШИМ на выходе D6 больше не рабоатет! + // функции времени (millis/delay) теперь работают некорректно + analogWrite(5, 30); // запустить ШИМ на D5 + + setPwmFreqnuency(3, PWM_31KHZ); // частота ШИМ на пинах 3 (и на 11) установлена на 31 кГц + analogWrite(3, 30); // запустить ШИМ на D3 + analogWrite(11, 200); // запустить ШИМ на D11 + + setPWM_20kHz(9); // частота шим на D9 (и автоматичсеки на D10) установлена на 20 кГц + // разрядность по умолчанию 8 бит (0-255) + + setPWM_9_10_resolution(PWM_10BIT); // ШИМ на пинах 9 и 10 теперь 10 битный (0-1023) + analogWrite(9, 512); // ШИМ на пине 9 с 50% заполнением + analogWrite(10, 700); // ШИМ на пине 9 с заполнением 700/1023 +} + +void loop() { + + +} diff --git a/examples/memtest/memtest.ino b/examples/memtest/memtest.ino new file mode 100644 index 0000000..2b76ffe --- /dev/null +++ b/examples/memtest/memtest.ino @@ -0,0 +1,28 @@ +// скетч для проверки занимаемой памяти + +void setup() { + pinMode(2, 1); + digitalWrite(1, 1); + digitalRead(0); + analogRead(0); + analogReference(DEFAULT); + analogWrite(9, 125); + millis(); + micros(); + delay(10); + delayMicroseconds(10); + tone(10, 10); + tone(10, 10, 100); + attachInterrupt(0, isr, 0); + detachInterrupt(0); + //uartBegin(); + //uartPrintln("kek OK"); + Serial.begin(9600); + Serial.println("kek OK"); +} +void isr(){} + +void loop() { + // put your main code here, to run repeatedly: + +} diff --git a/examples/parseTest/parseTest.ino b/examples/parseTest/parseTest.ino new file mode 100644 index 0000000..9d5a8b1 --- /dev/null +++ b/examples/parseTest/parseTest.ino @@ -0,0 +1,21 @@ +// пример работы с функцией uartParsePacket +// функция принимает из порта строку вида +// $10 21 458 63 8 45 875 215; +// и запихивает в массив dataArray + +int dataArray[8]; + +void setup() { + uartBegin(); // открыть на 9600 +} + +void loop() { + // $10 21 458 63 8 45 875 215; + if (uartParsePacket((int*)dataArray)) { + for (byte i = 0; i < 8; i++) { + uartPrint(dataArray[i]); + uartPrint(" "); + } + uartPrintln(); + } +} diff --git a/examples/printTest/printTest.ino b/examples/printTest/printTest.ino new file mode 100644 index 0000000..6be444b --- /dev/null +++ b/examples/printTest/printTest.ino @@ -0,0 +1,37 @@ +// тест вывода в порт разных типов данных + +int8_t data1 = -50; +uint8_t data2 = 125; +int16_t data3 = -2000; +uint16_t data4 = 30000; +int32_t data5 = -70000; +uint32_t data6 = 4194967295; +float data7 = 3681.65424; +float data8 = -4375.12353; +String data9 = "LOL LOL"; + +const char *data10[] = { + "LOL", + "KEK", + "CHEBUREK", +}; + +void setup() { + uartBegin(); + uartPrintln(data1); + uartPrintln(data2); + uartPrintln(data3); + uartPrintln(data4); + uartPrintln(data5); + uartPrintln(data6); + uartPrintln(data7); + uartPrintln(data8, 3); + uartPrintln(data9); + uartPrintln("KEK KEK"); + uartPrintln(F("KEK KEK MACRO")); + uartPrintln(data10[2]); +} + +void loop() { + +} diff --git a/package_GyverCore_index.json b/package_GyverCore_index.json index 1dd6cad..f305b51 100644 --- a/package_GyverCore_index.json +++ b/package_GyverCore_index.json @@ -16,10 +16,10 @@ "category": "Contributed", "url": "https://github.com/AlexGyver/GyverCore/releases/download/GyverCore/GyverCore.zip", "archiveFileName": "GyverCore.zip", - "checksum": "MD5:758f491c55f177cca874f20eaf1d6e63", - "size": "139848", + "checksum": "MD5:c304d158e055df8911457ed1aa42fae4", + "size": "137283", "boards": [ - {"name": "ATmega328 boards"} + {"name": "ATmega328/168 based boards"} ], "toolsDependencies": [] }