Сигнал в цифровом виде подаётся на вход D2 ардуино. Никаких дополнительных библиотек скетчу не нужно.
Код:
#define InputPIN 2
volatile unsigned long PPeriod = 0; // текущее значение полупериода
volatile unsigned int PPeriod_sred = 0; // среднее значение границы длинны полупериода
unsigned int Tpp = 0; // расчётное значение полупериода для вывода
volatile unsigned long iMicros_old = 0; // предыдущее значение микросекунд
volatile boolean Pik = false; // есть изменение сигнала
volatile boolean Plong = false; // "длинный" полупериод
byte BUFF[512]; // буфер данных
unsigned int CWB = 0; // индекс записи в буфер
byte bBit = 14; // индекс записываемого полубита
byte A = 0; // записываемый байт
byte B = 0; // записываемый бит
int i0 = 0; // счётчик циклов без сигнала
//unsigned int j;
void setup() //процедура setup
{
pinMode(InputPIN, INPUT); //объявляем пин как вход
pinMode(13, OUTPUT); // объявляем пин как выход
attachInterrupt(0, TakeTime, CHANGE); // включаем обработку внешнего прерывания
Serial.begin(9600);
}
void loop() //процедура loop
{
if (Pik) { // Произошло изменение сигнала
Pik = false;
i0 = 0;
if (Plong) { // получен длинный полупериод
B ^= 1; // инвертируем бит
A = (A<<1)+B; // заносим бит
bBit--; // уменьшаем счётчик полубитов
}
else { // получен короткий полупериод
if (bBit & 1) { // нечётный полубит
A = (A<<1)+B; // заносим бит
}
}
// ===================================
if (bBit > 1) {
bBit--; // счётчик -1
}
else {
if (CWB < 512) BUFF[CWB] = A;
CWB++;
A = 0;
bBit += 15;
}
// ====================================
digitalWrite(13, HIGH); // зажигаем светодиод -- сигнал есть
}
else{ // изменения сигнала не было
if (i0 < 9) { // считаем 10 раз
i0++;
}
if (i0 == 8) { // на восьмой раз выводим тестовую инфу
digitalWrite(13, LOW); // гасим светодиод -- сигнала нет
Serial.println("--------");
for (int j = 0; j<=511; j++) {
Serial.print(BUFF[j], HEX);
Serial.print('-');
if (((j+1)%16) == 0) Serial.println('-');
}
Serial.println("--------");
Serial.println(PPeriod_sred); // граница короткий/длинный полупериод
if (((PPeriod_sred/3*2)%8) < 4) { // полупериод для последующего вывода...
Tpp = (PPeriod_sred/12)*8; // округление до кратного 8 в меньшую сторону
}
else {
Tpp = ((PPeriod_sred/12)+1)*8;// округление до кратного 8 в большую сторону
}
Serial.println(Tpp); // расчётное значение длинны полупериода для вывода
// сбрасываем счётчики -- сигнала слишьком долго нет
CWB = 0;
A = 0;
B = 0;
bBit = 14;
delay(100);
}
}
delayMicroseconds(128); // задержка...
}
void TakeTime()
{
PPeriod = micros() - iMicros_old;
iMicros_old += PPeriod;
if (PPeriod < 1000) { // началось...
if (PPeriod_sred != 0) {
if (!Plong) {
if (PPeriod > PPeriod_sred) Plong = true; // тек. полупериод стал длинный
}
else {
if (PPeriod < PPeriod_sred) Plong = false; // тек. полупериод стал короткий
}
// если ни то, ни другое -- они равны, т.е. Plong без изменений
if (!Plong) { // если полупериод короткий, пересчитываем среднее значение
PPeriod_sred = (PPeriod_sred + PPeriod/2*3)/2;
}
}
else {
PPeriod_sred = PPeriod/2*3; // если ещё нет статистики, берём текущее значение
}
Pik = true; // есть сигнал
}
else { // был перерыв в сигнале
if (PPeriod_sred != 0) {
PPeriod_sred = 0; // обнуляем среднее значение
Plong = false; // и считаем, что будет короткий полупериод
}
}
}