#include <TimerOne.h>
const int pinLED = 13;
volatile bool activete = false; // вкл/выкл кнопки
int ledState = LOW; //состояние светодиода
// Пауза между элементами одного знака — одна точка, между знаками в слове — 3 точки
const int32_t DBE = 200; // Delay Between Elements In One Letter
const int32_t DBL = 600; // Delay Between Letters In One Word
const int32_t char_S[3] = {200, 200, 200}; // ...
const int32_t char_O[3] = {600, 600, 600}; // ---
void setup()
{
pinMode(2, INPUT_PULLUP); // подтягивающий резистор на входе прерывания
attachInterrupt(0, myEventListener, FALLING); //разрешение внешнего прерывания (вывод 2 Arduino UNO)
pinMode(pinLED, OUTPUT);
Timer1.initialize(200000); // инициазизируем таймер, значение 200 мс как самое частое
Serial.begin(9600);
}
void loop(void)
{
}
/*
Устанавливает периор таймера в соостветсвии с конкретным символом
@param {char*} c - Строчка (массив символов) для сигнала Морзе
@param {int} s - Количество символов в строке
*/
void EmitSignal(char *c, int s){
static int charIndex = 0; // Итератор для прохода по массиву символов
static int iter = 0; // Итератор для прохода по паузам (. или -) в одном символе
static int count = 1;
static int LettArrSize = -1; // Количество пауз (. или -) в одном символе
if(iter == LettArrSize){ // Выводим пробел буквами элементами в слове
Timer1.setPeriod(DBL * 1000);
if(charIndex == s - 1){ // Если мы на последней букве, сбрасываем итераток строки
charIndex = 0;
}
else{
charIndex++;
}
count = 1;
iter = 0;
return 0;
}
if(count % 2 == 0){ // Выводим пробел между элементами в букве
Timer1.setPeriod(DBE * 1000);
count = 1;
return 0;
}
switch (c[charIndex]){
case 'S':
LettArrSize = sizeof(char_S)/sizeof(char_S[0]);
Timer1.setPeriod(char_S[iter] * 1000);
break;
case 'O':
LettArrSize = sizeof(char_O)/sizeof(char_O[0]);
Timer1.setPeriod(char_O[iter] * 1000);
break;
default:
break;
}
count++;
iter++;
}
void Blink(void){
EmitSignal("SOS", 3);
if (ledState == LOW) {
ledState = HIGH;
}
else {
ledState = LOW;
}
digitalWrite(pinLED, ledState);
}
//Функция обработки внешнего прерывания
void myEventListener()
{
activete = !activete;
if(activete){
Timer1.attachInterrupt(Blink); // вызывать BlickSOS каждые 200 мс.
}
else{
digitalWrite(pinLED, LOW); // Выключает светодиод, если кнопка была нажата пока он включен
Timer1.detachInterrupt(); // отвязывает функцию с миганием
}
}