mirror of
https://github.com/AlexGyver/GyverCore.git
synced 2025-04-19 08:42:16 +03:00
add
This commit is contained in:
parent
983b80cb94
commit
c52f478bb5
@ -5,7 +5,7 @@ menu.timers=Timers
|
|||||||
|
|
||||||
######################
|
######################
|
||||||
|
|
||||||
nano.name=ATmega328P based
|
nano.name=ATmega328/168 based
|
||||||
|
|
||||||
nano.upload.tool=avrdude
|
nano.upload.tool=avrdude
|
||||||
nano.upload.protocol=arduino
|
nano.upload.protocol=arduino
|
||||||
@ -21,10 +21,10 @@ nano.build.core=arduino
|
|||||||
|
|
||||||
## timer0 OVF ON/OFF
|
## 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.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
|
nano.menu.timers.no_millis.build.variant=nomillis
|
||||||
|
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ nano.menu.cpu.atmega328old.build.mcu=atmega328p
|
|||||||
|
|
||||||
## ATmega328P - NO bootloader
|
## 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_size=32768
|
||||||
nano.menu.cpu.atmega328noBoot.upload.maximum_data_size=2048
|
nano.menu.cpu.atmega328noBoot.upload.maximum_data_size=2048
|
||||||
@ -107,7 +107,7 @@ nano.menu.cpu.atmega168old.build.mcu=atmega168
|
|||||||
|
|
||||||
## ATmega168 - NO bootloader
|
## 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_size=16144
|
||||||
nano.menu.cpu.atmega168noBoot.upload.maximum_data_size=1024
|
nano.menu.cpu.atmega168noBoot.upload.maximum_data_size=1024
|
||||||
|
@ -161,62 +161,7 @@ void detachInterrupt(uint8_t);
|
|||||||
void setup(void);
|
void setup(void);
|
||||||
void loop(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
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // 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 pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
|
||||||
unsigned long pulseInLong(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 tone(uint8_t pin , uint16_t freq, uint32_t duration = 0);
|
||||||
void noTone(uint8_t _pin);
|
void noTone(uint8_t pin);
|
||||||
|
|
||||||
// WMath prototypes
|
// WMath prototypes
|
||||||
long random(long);
|
long random(long);
|
||||||
|
@ -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 <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include "Arduino.h"
|
#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__)
|
void tone(uint8_t pin , uint16_t freq, uint32_t duration = 0){
|
||||||
#define TCCR2A TCCR2
|
tone_pin = pin; // присвоили номер пина для прерывания
|
||||||
#define TCCR2B TCCR2
|
willStop = duration;// если введено время генерации - будет ненулевым
|
||||||
#define COM2A1 COM21
|
toggle_top = (freq * duration)/500; // расчет кол-ва toggl'ов за указанное время генерации
|
||||||
#define COM2A0 COM20
|
TCCR2A = (1<<WGM21); // вкл CTC
|
||||||
#define OCR2A OCR2
|
TIMSK2 |= (1<<OCIE2A); //Вкл прерывание
|
||||||
#define TIMSK2 TIMSK
|
if(freq < 122){ // максимальный делитель
|
||||||
#define OCIE2A OCIE2
|
TCCR2B = 0x7; // присвоили делитель
|
||||||
#define TIMER2_COMPA_vect TIMER2_COMP_vect
|
OCR2A = (15625/freq)-1; // рассчитали top для CTC
|
||||||
#define TIMSK1 TIMSK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
if(freq > 244){ // минимальный делитель
|
||||||
|
TCCR2B = 0x5; // по аналогии см выше
|
||||||
|
OCR2A = (62500/freq)-1; // по аналогии см выше
|
||||||
|
}
|
||||||
|
else { // средний делитель
|
||||||
|
TCCR2B = 0x6; // по аналогии см выше
|
||||||
|
OCR2A = (125000/freq)-1; // по аналогии см выше
|
||||||
|
}
|
||||||
|
toggle_counter = 0; // обнулили счетчик toggl'ов
|
||||||
}
|
}
|
||||||
|
|
||||||
// search for an unused timer.
|
void noTone(uint8_t pin){ // если вызван noTone
|
||||||
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
|
digitalWrite(pin,0);// устанавливаем 0 на выходе
|
||||||
if (tone_pins[i] == 255) {
|
TIMSK2 &=~ (1<<OCIE2A); // остановить прерывания
|
||||||
tone_pins[i] = _pin;
|
TCCR2A = 0b00000011; // установить стандартные настройки для таймера 2
|
||||||
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
|
TCCR2B = 0b00000100;
|
||||||
break;
|
OCR2A = 0; //обнуляем регистр сравнения
|
||||||
}
|
TCCR2A &=~ ((1<<COM2A1)|(1<<COM2B1)); // откл регистры сравнения (подстраховка)
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ISR(TIMER2_COMPA_vect){ // прерывание генерации
|
||||||
// frequency (in hertz) and duration (in milliseconds).
|
if(toggle_counter < toggle_top || !willStop ){ // если количество toggl'ов не достигло предела или процесс бесконечен - генерация
|
||||||
|
digitalToggle(tone_pin); // иневертируем состоние на ноге
|
||||||
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
|
toggle_counter++; // икремент счетчика
|
||||||
{
|
|
||||||
uint8_t prescalarbits = 0b001;
|
|
||||||
long toggle_count = 0;
|
|
||||||
uint32_t ocr = 0;
|
|
||||||
int8_t _timer;
|
|
||||||
|
|
||||||
_timer = toneBegin(_pin);
|
|
||||||
|
|
||||||
if (_timer >= 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
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
|
/* Главный цикл программы */
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
WDTCSR = 0; // wdt disable
|
WDTCSR = 0; // Первым делом отключаем ватчдог
|
||||||
init();
|
init(); // инициализация таймеров и ацп
|
||||||
setup();
|
setup(); // функция setup
|
||||||
while (1) {
|
while (1) { // бесконечный цикл
|
||||||
loop();
|
loop(); // функция loop
|
||||||
if (serialEventRun) serialEventRun();
|
if (serialEventRun) serialEventRun(); // обслуживание serial
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "timeControl.h"
|
#include "timeControl.h"
|
||||||
|
/* функции времени и инициализация таймеров , АЦП*/
|
||||||
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) // 1024
|
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) // 1024
|
||||||
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) // 1
|
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) // 1
|
||||||
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) // 3
|
#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;
|
volatile unsigned long timer0_millis = 0;
|
||||||
static unsigned char timer0_fract = 0;
|
static unsigned char timer0_fract = 0;
|
||||||
|
|
||||||
#ifdef MILLIS_TMRS
|
#ifdef MILLIS_TMRS // переключатель, отключающий millis(), освобождающий вектор прерывания
|
||||||
ISR(TIMER0_OVF_vect)
|
ISR(TIMER0_OVF_vect)
|
||||||
{
|
{
|
||||||
timer0_millis++;
|
timer0_millis++;
|
||||||
@ -24,20 +24,20 @@ ISR(TIMER0_OVF_vect)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned long millis() {
|
unsigned long millis() {
|
||||||
cli();
|
cli(); // остановить счет
|
||||||
unsigned long m = timer0_millis;
|
unsigned long m = timer0_millis; // перехватить значение
|
||||||
sei();
|
sei(); // продолжить счет
|
||||||
return m;
|
return m; // вернуть миллисекунды
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long micros() {
|
unsigned long micros() {
|
||||||
cli();
|
cli(); // остановить прерывания
|
||||||
unsigned long m = timer0_overflow_count;
|
unsigned long m = timer0_overflow_count; // счет переполнений
|
||||||
uint8_t t = TCNT0;
|
uint8_t t = TCNT0; // считать содержимое счетного регистра
|
||||||
if ((TIFR0 & _BV(TOV0)) && (t < 255))
|
if ((TIFR0 & _BV(TOV0)) && (t < 255)) //инкремент по переполнению
|
||||||
m++;
|
m++;
|
||||||
sei();
|
sei(); // продолжить счет
|
||||||
return (long)(((m << 8) + t) * 4);
|
return (long)(((m << 8) + t) * 4); // вернуть микросекунды
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -79,9 +79,9 @@ 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();
|
yield();
|
||||||
while ( ms > 0 && (micros() - start) >= 1000) {
|
while ( ms > 0 && (micros() - start) >= 1000) {
|
||||||
ms--;
|
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 F_CPU >= 16000000L
|
||||||
if (us <= 1) return; // = 3 cycles, (4 when true)
|
if (us <= 1) return; // = 3 cycles, (4 when true)
|
||||||
us <<= 2; // x4 us, = 4 cycles
|
us <<= 2; // x4 us, = 4 cycles
|
||||||
us -= 5;
|
us -= 5;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// busy wait
|
// busy wait
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"1: sbiw %0,1" "\n\t" // 2 cycles
|
"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 */
|
/* timer 0 */
|
||||||
TCCR0A = 0b00000011; // fast pwm 8 bit
|
TCCR0A = 0b00000011; // fast pwm 8 bit
|
||||||
TCCR0B = 0b00000011; // prescaler 64
|
TCCR0B = 0b00000011; // делитель 64
|
||||||
TIMSK0 |= (1<<TOIE0); // ovf interrupt enable
|
TIMSK0 |= (1<<TOIE0); // ovf interrupt вкл
|
||||||
/* timer 1 */
|
/* timer 1 */
|
||||||
TCCR1A = 0b00000001; // fast pwm 8 bit
|
TCCR1A = 0b00000001; // fast pwm 8 bit
|
||||||
TCCR1B = 0b00001011; // prescaler 64
|
TCCR1B = 0b00001011; // делитель 64
|
||||||
/* timer 2 */
|
/* timer 2 */
|
||||||
TCCR2A = 0b00000011; // fast pwm 8 bit
|
TCCR2A = 0b00000011; // fast pwm 8 bit
|
||||||
TCCR2B = 0b00000100; // prescaler 64
|
TCCR2B = 0b00000100; // делитель 64
|
||||||
/* adc */
|
/* adc */
|
||||||
ADMUX = 0b01001111; // reference - vcc , adc parked to gnd
|
ADMUX = 0b01001111; // reference - vcc , вход ацп припаркован к gnd
|
||||||
ADCSRA = 0b10000010; // prescaler - 4 [0,1,2 bits - prescaler]
|
ADCSRA = 0b10000010; // делитель - 4 [0,1,2 bits - делитель]
|
||||||
/* ADC prescalers: 001 >> /2 010 >> /4 011 >> /8 100 >> /16 101 >> /32 110 >> /64 111 >> /128*/
|
/* ADC prescalers: 001 >> /2 010 >> /4 011 >> /8 100 >> /16 101 >> /32 110 >> /64 111 >> /128*/
|
||||||
/* UART */
|
/* UART */
|
||||||
UCSR0B = 0;
|
UCSR0B = 0; // пока не вызван Serial.begin / uartBegin выводы 0/1 свободны для работы.
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
@ -1,44 +1,46 @@
|
|||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
/* Реализация облегченного Serial от AlexGyver & Egor 'Nich1con' Zaharov*/
|
||||||
|
|
||||||
// ===== INIT =====
|
// ===== INIT =====
|
||||||
void uartBegin(uint32_t baudrate){
|
void uartBegin(uint32_t baudrate){ // инициализация uart
|
||||||
uint16_t speed = (2000000/baudrate)-1;
|
uint16_t speed = (2000000/baudrate)-1; // расчет baudrate
|
||||||
UBRR0H = highByte(speed);
|
UBRR0H = highByte(speed); // установка baudrate
|
||||||
UBRR0L = lowByte(speed);
|
UBRR0L = lowByte(speed);
|
||||||
UCSR0A = (1 << U2X0);
|
UCSR0A = (1 << U2X0); // вкл удвоенную скорость
|
||||||
UCSR0B = ((1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0));
|
UCSR0B = ((1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)); // вкл uart
|
||||||
UCSR0C = ((1<<UCSZ01) | (1<<UCSZ00));
|
UCSR0C = ((1<<UCSZ01) | (1<<UCSZ00)); // настраиваем формат данных
|
||||||
}
|
}
|
||||||
void uartBegin(void) {
|
void uartBegin(void) { // вызов uartBegin без параметра настроит скорость 9600
|
||||||
uartBegin(9600);
|
uartBegin(9600);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uartEnd(){
|
void uartEnd(){ // откл uart
|
||||||
UCSR0B = 0;
|
UCSR0B = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== READ =====
|
// ===== READ =====
|
||||||
volatile char _UART_RX_BUFFER[64];
|
volatile char _UART_RX_BUFFER[64];
|
||||||
volatile int8_t _UART_RX_COUNTER;
|
volatile int8_t _UART_RX_COUNTER;
|
||||||
ISR(USART_RX_vect) {
|
ISR(USART_RX_vect) { // чекаем твои байты по прерыванию
|
||||||
_UART_RX_BUFFER[_UART_RX_COUNTER] = UDR0;
|
_UART_RX_BUFFER[_UART_RX_COUNTER] = UDR0; // пишем в массив "буфер"
|
||||||
_UART_RX_COUNTER++;
|
_UART_RX_COUNTER++;
|
||||||
}
|
}
|
||||||
|
|
||||||
char uartRead() {
|
char uartRead() { // чтение данных из буфера
|
||||||
char thisChar = _UART_RX_BUFFER[0];
|
char thisChar = _UART_RX_BUFFER[0];
|
||||||
for (byte i = 0; i < _UART_RX_COUNTER; i++) _UART_RX_BUFFER[i] = _UART_RX_BUFFER[i + 1];
|
for (byte i = 0; i < _UART_RX_COUNTER; i++) _UART_RX_BUFFER[i] = _UART_RX_BUFFER[i + 1];
|
||||||
if (--_UART_RX_COUNTER < 0) _UART_RX_COUNTER = 0;
|
if (--_UART_RX_COUNTER < 0) _UART_RX_COUNTER = 0;
|
||||||
return thisChar;
|
return thisChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean uartAvailable() { // проверка доступности данных в буфере
|
||||||
|
return _UART_RX_COUNTER;
|
||||||
|
}
|
||||||
|
/* Дальше он писал сам, там жесть полная */
|
||||||
char uartPeek() {
|
char uartPeek() {
|
||||||
return _UART_RX_BUFFER[0];
|
return _UART_RX_BUFFER[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean uartAvailable() {
|
|
||||||
return _UART_RX_COUNTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartClear() {
|
void uartClear() {
|
||||||
_UART_RX_COUNTER = 0;
|
_UART_RX_COUNTER = 0;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#ifndef uart_h
|
/* Облегченный Serial */
|
||||||
|
|
||||||
|
#ifndef uart_h
|
||||||
#define uart_h
|
#define uart_h
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
@ -1,29 +1,61 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#include "wiring_private.h"
|
|
||||||
//#include "pins_arduino.h"
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
#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
|
||||||
const uint16_t PROGMEM port_to_mode_PGM[] = {
|
const uint16_t PROGMEM port_to_mode_PGM[] = {
|
||||||
NOT_A_PORT,
|
NOT_A_PORT,
|
||||||
NOT_A_PORT,
|
NOT_A_PORT,
|
||||||
|
@ -1,25 +1,4 @@
|
|||||||
/*
|
/* Програмный SPI */
|
||||||
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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
|
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
|
||||||
|
@ -40,6 +40,12 @@ uartParsePacket KEYWORD2
|
|||||||
######################################
|
######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
#######################################
|
#######################################
|
||||||
|
PWM_8BIT LITERAL1
|
||||||
|
PWM_10BIT LITERAL1
|
||||||
|
PWM_DEFAULT LITERAL1
|
||||||
|
PWM_8KHZ LITERAL1
|
||||||
|
PWM_31KHZ LITERAL1
|
||||||
|
|
||||||
THERMOMETR LITERAL1
|
THERMOMETR LITERAL1
|
||||||
A0 LITERAL1
|
A0 LITERAL1
|
||||||
A1 LITERAL1
|
A1 LITERAL1
|
||||||
|
30
README.md
30
README.md
@ -1,5 +1,5 @@
|
|||||||
# GyverCore for ATmega328p/168p
|
# GyverCore for ATmega328/168
|
||||||
Быстрое ядро для Arduino IDE. **В разработке**
|
Быстрое и лёгкое ядро для Arduino IDE.
|
||||||
Основано на оригинальном ядре Arduino версии 1.8.9, большинство функций заменены на более быстрые и лёгкие аналоги, убрано всё лишнее и не относящееся к микроконтроллеру ATmega328p, убран почти весь Wiring-мусор, код упрощён и причёсан.
|
Основано на оригинальном ядре Arduino версии 1.8.9, большинство функций заменены на более быстрые и лёгкие аналоги, убрано всё лишнее и не относящееся к микроконтроллеру ATmega328p, убран почти весь Wiring-мусор, код упрощён и причёсан.
|
||||||
|
|
||||||
## Установка
|
## Установка
|
||||||
@ -14,12 +14,13 @@
|
|||||||
- Листай в самый низ, пока не увидишь **GyverCore**
|
- Листай в самый низ, пока не увидишь **GyverCore**
|
||||||
- Жми **Установка**
|
- Жми **Установка**
|
||||||
- Закрой окно
|
- Закрой окно
|
||||||
- Выбери плату в **Инструменты > Плата > GyverCore > ATmega328p based**
|
- Выбери плату в **Инструменты > Плата > GyverCore > ATmega328/168 based**
|
||||||
- Выбери в **CPU & BOOT** нужный вариант загрузчика
|
- Выбери в **CPU & BOOT** нужный вариант загрузчика
|
||||||
- Готово
|
- Готово!
|
||||||
|
- *Примечание*: файлы ядра находятся по пути *C:\Users\Username\AppData\Local\Arduino15\packages\GyverCore\hardware\avr\1.0.0\*
|
||||||
|
|
||||||
# Изменения
|
## Изменения
|
||||||
## Облегчено и ускорено
|
### Облегчено и ускорено
|
||||||
Время выполнения функций, мкс
|
Время выполнения функций, мкс
|
||||||
|
|
||||||
Функция | Arduino | GyverCore | Быстрее в
|
Функция | Arduino | GyverCore | Быстрее в
|
||||||
@ -32,6 +33,7 @@ analogRead | 112.01 us | 5.41 us | 20.70
|
|||||||
analogReference | 0.00 us | 0.69 us | 0.00
|
analogReference | 0.00 us | 0.69 us | 0.00
|
||||||
attachInterrupt | 1.20 us | 1.18 us | 1.02
|
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, байт
|
Занимаемое место, Flash, байт
|
||||||
|
|
||||||
@ -45,6 +47,7 @@ analogRead | 32 | 72 | -40
|
|||||||
analogReference | 0 | 32 | -32
|
analogReference | 0 | 32 | -32
|
||||||
attachInterrupt | 212 | 180 | 32
|
attachInterrupt | 212 | 180 | 32
|
||||||
detachInterrupt | 198 | 150 | 48
|
detachInterrupt | 198 | 150 | 48
|
||||||
|
tone | 1410 | 740 | 670
|
||||||
Serial.begin | 1028 | 166 | 862
|
Serial.begin | 1028 | 166 | 862
|
||||||
print long | 1094 | 326 | 768
|
print long | 1094 | 326 | 768
|
||||||
print string | 2100 | 1484 | 616
|
print string | 2100 | 1484 | 616
|
||||||
@ -54,8 +57,11 @@ 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**
|
- Подсветка в коде **A0**, **A1**.. **A7**
|
||||||
- Макрос **bitToggle**(value, bit), инвертирует состояние бита bit в байте value
|
- Макрос **bitToggle**(value, bit), инвертирует состояние бита bit в байте value
|
||||||
- Функция **digitalToggle**(pin), инвертирует состояние пина
|
- Функция **digitalToggle**(pin), инвертирует состояние пина
|
||||||
@ -86,12 +92,16 @@ parseFloat | 1070 | 246 | 824
|
|||||||
- **uartParseFloat()** - принять число float
|
- **uartParseFloat()** - принять число float
|
||||||
- **uartParsePacket(dataArray)** - принять пакет вида **$50 60 70;** в массив dataArray (смотри пример)
|
- **uartParsePacket(dataArray)** - принять пакет вида **$50 60 70;** в массив dataArray (смотри пример)
|
||||||
|
|
||||||
|
### Убарно
|
||||||
|
Убраны всякие сервисные файлы и прочий хлам, не относящийся к ATmega328 (wifi, USB). Ядро полностью совместимо с остальными библиотеками, ничего из стандартных функций не вырезано.
|
||||||
|
|
||||||
## Дополнительно
|
## Дополнительно
|
||||||
### Настройки прошивки
|
### Настройки прошивки
|
||||||
- Добавлен вариант прошивки без загрузчика (во всю доступную Flash память) для прошивки через ISP
|
- Смотри примеры в папке examples (в корне этого репозитория!)
|
||||||
- Добавлен вариант прошивки с отключенными функциями времени (освобождает вектор **TIMER0_OVF_vect** для личного пользования)
|
- Добавлен вариант прошивки без загрузчика **ATmega 328/168 without bootloader** (во всю доступную Flash память) для прошивки через ISP
|
||||||
|
- Добавлен вариант прошивки с отключенными функциями времени **with/without millis** (освобождает вектор **TIMER0_OVF_vect** для личного пользования)
|
||||||
|
|
||||||
### Больше контроля!
|
## Больше контроля!
|
||||||
Для большего контроля за периферией микроконтроллера рекомендую попробовать следующие наши библиотеки:
|
Для большего контроля за периферией микроконтроллера рекомендую попробовать следующие наши библиотеки:
|
||||||
- **directTimers** - полный контроль над таймерами/счётчиками ATmega328
|
- **directTimers** - полный контроль над таймерами/счётчиками ATmega328
|
||||||
- **directADC** - полный контроль над АЦП и компаратором ATmega328
|
- **directADC** - полный контроль над АЦП и компаратором ATmega328
|
||||||
|
22
examples/advancedPWM/advancedPWM.ino
Normal file
22
examples/advancedPWM/advancedPWM.ino
Normal file
@ -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() {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
28
examples/memtest/memtest.ino
Normal file
28
examples/memtest/memtest.ino
Normal file
@ -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:
|
||||||
|
|
||||||
|
}
|
21
examples/parseTest/parseTest.ino
Normal file
21
examples/parseTest/parseTest.ino
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
37
examples/printTest/printTest.ino
Normal file
37
examples/printTest/printTest.ino
Normal file
@ -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() {
|
||||||
|
|
||||||
|
}
|
@ -16,10 +16,10 @@
|
|||||||
"category": "Contributed",
|
"category": "Contributed",
|
||||||
"url": "https://github.com/AlexGyver/GyverCore/releases/download/GyverCore/GyverCore.zip",
|
"url": "https://github.com/AlexGyver/GyverCore/releases/download/GyverCore/GyverCore.zip",
|
||||||
"archiveFileName": "GyverCore.zip",
|
"archiveFileName": "GyverCore.zip",
|
||||||
"checksum": "MD5:758f491c55f177cca874f20eaf1d6e63",
|
"checksum": "MD5:c304d158e055df8911457ed1aa42fae4",
|
||||||
"size": "139848",
|
"size": "137283",
|
||||||
"boards": [
|
"boards": [
|
||||||
{"name": "ATmega328 boards"}
|
{"name": "ATmega328/168 based boards"}
|
||||||
],
|
],
|
||||||
"toolsDependencies": []
|
"toolsDependencies": []
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user