From 48e1fa1e983a4cbd3df74297a103eb8af4c8a4a1 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 17 Jun 2021 12:49:46 +0300 Subject: [PATCH] v1.2 --- README.md | 41 +-- examples/demo_rx/demo_rx.ino | 26 +- examples/demo_tx/demo_tx.ino | 25 +- examples/isr_rx/isr_rx.ino | 8 +- examples/raw_rx/raw_rx.ino | 4 +- examples/raw_tx/raw_tx.ino | 6 +- examples/rx433_lcd/rx433_lcd.ino | 1 + examples/rx433_struct/rx433_struct.ino | 3 +- examples/tx433_struct/tx433_struct.ino | 6 +- keywords.txt | 7 +- library.properties | 2 +- src/Gyver433.h | 415 +++++++++++++------------ 12 files changed, 297 insertions(+), 247 deletions(-) diff --git a/README.md b/README.md index b72b849..234ca4c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Библиотека для радиомодулей 433 МГц и Arduino - Супер лёгкая либа, заведётся даже на тини13 (отправка) - Поддержка кривых китайских модулей -- Интерфейс Manchester Coding (v1.1) +- Интерфейс Manchester или Pulselength - Встроенный CRC контроль целостности (CRC8 или XOR) - Ускоренный алгоритм IO для AVR Arduino - Опционально работа в прерывании (приём данных) @@ -36,18 +36,26 @@ ## Инициализация ```cpp -//Классы: -Gyver433_RX // приёмник -Gyver433_TX // передатчик +// === КЛАССЫ === +// Gyver433_RX - приёмник +// Gyver433_TX - передатчик +// === ИНИЦИАЛИЗАЦИЯ === +Gyver433_xx<пин> xx; +Gyver433_xx<пин, буфер> xx; Gyver433_xx<пин, буфер, CRC> xx; // пин: цифровой пин -// буфер: размер буфера в байтах. На "ручную" отправку буфер не нужен (пример raw_tx). По умолч. 64 байта +// буфер: размер буфера в байтах. На "ручную" отправку буфер не нужен. По умолч. 64 // CRC: проверка целостности данных: G433_CRC8 (надёжный), G433_XOR (лёгкий), G433_NOCRC (отключено). По умолч. G433_CRC8 -// Дефайны-настройки перед подключением библиотеки -#define G433_SLOW_MODE // "медленный режим" для синих модулей SYN480R -#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с + +// === ДЕФАЙНЫ-НАСТРОЙКИ === +// вызывать перед подключением библиотеки +#define G433_FAST // [TX] короткая синхронизация для зелёных модулей +#define G433_MEDIUM // [TX] средняя синхронизация при отправке на SYN480R ЧАЩЕ 400мс (активно по умолчанию) +#define G433_SLOW // [TX] длинная синхронизация при отправке на SYN480R РЕЖЕ 400мс +#define G433_MANCHESTER // [должно быть одинаково на RX и TX] интерфейс Manchester Coding для экспериментов =) +#define G433_SPEED 1000 // [должно быть одинаково на RX и TX] скорость 100-8000 бит/с, по умолч. 2000 бит/с ``` @@ -79,7 +87,6 @@ uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size); // ручной CRC XOR ![Logo](/doc/scheme.jpg) ### Отправка ```cpp -#define G433_SLOW_MODE #include Gyver433_TX<2, 20> tx; // указали пин и размер буфера @@ -101,7 +108,6 @@ void loop() { ### Приём ```cpp -#define G433_SLOW_MODE #include Gyver433_RX<2, 20> rx; // указали пин и размер буфера @@ -110,8 +116,8 @@ void setup() { } void loop() { - if (rx.tickWait()) { - Serial.write(rx.buffer, rx.size); + if (rx.tickWait()) { // если успешно принято больше 0 + Serial.write(rx.buffer, rx.size); // выводим Serial.println(); } } @@ -119,7 +125,6 @@ void loop() { ### Приём в прерывании ```cpp -#define G433_SLOW_MODE #include Gyver433_RX<2, 20> rx; // указали пин и размер буфера @@ -129,16 +134,15 @@ void setup() { } void isr() { - rx.tickISR(); // спец тикер вызывается в прерывании + rx.tickISR(); // спец. тикер вызывается в прерывании } void loop() { - // вернёт количество удачно принятых в прерывании байт - if (rx.gotData()) { - Serial.write(rx.buffer, rx.size); + if (rx.gotData()) { // если успешно принято больше 0 + Serial.write(rx.buffer, rx.size); // выводим Serial.println(); } - delay(200); // имитация загруженного кода + delay(200); // имитация загруженного кода } ``` @@ -146,6 +150,7 @@ void loop() { ## Версии - v1.0 - v1.1 - оптимизация, новый интерфейс, поддержка дешёвых синих модулей, работа в прерывании +- v1.2 - улучшение качества связи, оптимизация работы в прерывании ## Баги и обратная связь diff --git a/examples/demo_rx/demo_rx.ino b/examples/demo_rx/demo_rx.ino index f676f0c..6766be2 100644 --- a/examples/demo_rx/demo_rx.ino +++ b/examples/demo_rx/demo_rx.ino @@ -1,21 +1,21 @@ +// демо-пример: инициализация и настройки // крупный приёмник SYN480R [VCC: 3.3-5.5V, logic: VCC] // или MX-RM-5V (RF-5V) [VCC: 5V, logic: 5V] -// "медленный режим" для синих модулей SYN480R -// Объявляется перед подключением библиотеки -// Зелёным модулям не нужен! -#define G433_SLOW_MODE - -// можно указать скорость, по умолч. стоит 2000 бит/с -// рабочий диапазон: 100-8000 бит/с -//#define G433_SPEED 1000 +// дефайны перед подключением библиотеки +//#define G433_MANCHESTER // интерфейс Manchester Coding для экспериментов =) +//#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с #include -// Gyver433_TX<пин, буфер, CRC> +//Gyver433_RX<пин> rx; +//Gyver433_RX<пин, буфер> rx; +//Gyver433_RX<пин, буфер, CRC> rx; + // пин: цифровой пин -// буфер: размер приёмного буфера в байтах +// буфер: размер буфера в байтах. По умолч. 64 // CRC: проверка целостности данных: G433_CRC8 (надёжный), G433_XOR (лёгкий), G433_NOCRC (отключено). По умолч. G433_CRC8 -Gyver433_RX<2, 20> rx; // указали пин и размер буфера + +Gyver433_RX<2, 20> rx; void setup() { Serial.begin(9600); @@ -25,7 +25,7 @@ void loop() { // "тик" опрашивает радио и вернёт количество успешно принятых байт // tick принимает асинхронно, но может ловить ошибки при загруженном коде // tickWait блокирует выполнение, но принимает данные чётко - + //if (rx.tick()) { if (rx.tickWait()) { // принятые данные доступны в .buffer @@ -33,4 +33,4 @@ void loop() { Serial.write(rx.buffer, rx.size); Serial.println(); } -} \ No newline at end of file +} diff --git a/examples/demo_tx/demo_tx.ino b/examples/demo_tx/demo_tx.ino index 848fd2f..03dba9c 100644 --- a/examples/demo_tx/demo_tx.ino +++ b/examples/demo_tx/demo_tx.ino @@ -1,21 +1,24 @@ +// демо-пример: инициализация и настройки // мелкий передатчик SYN115 [VCC: 1.8-3.6V, logic: VCC] // или FS1000A [VCC: 3-12V, logic: 5V] -// "медленный режим" для синих модулей SYN115 -// Объявляется перед подключением библиотеки -// зелёным модулям не нужен! -#define G433_SLOW_MODE - -// можно указать скорость, по умолч. стоит 2000 бит/с -// рабочий диапазон: 100-8000 бит/с -//#define G433_SPEED 1000 +// дефайны перед подключением библиотеки +//#define G433_FAST // короткая синхронизация для зелёных модулей +//#define G433_MEDIUM // средняя синхронизация для SYN480R при отправке ЧАЩЕ 400мс (активно по умолчанию) +//#define G433_SLOW // длинная синхронизация для SYN480R при отправке РЕЖЕ 400мс +//#define G433_MANCHESTER // интерфейс Manchester Coding для экспериментов =) +//#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с #include -// Gyver433_TX<пин, буфер, CRC> +//Gyver433_TX<пин> tx; +//Gyver433_TX<пин, буфер> tx; +//Gyver433_TX<пин, буфер, CRC> tx; + // пин: цифровой пин // буфер: размер буфера в байтах. На "ручную" отправку буфер не нужен. По умолч. 64 // CRC: проверка целостности данных: G433_CRC8 (надёжный), G433_XOR (лёгкий), G433_NOCRC (отключено). По умолч. G433_CRC8 -Gyver433_TX<2, 20> tx; // указали пин и размер буфера + +Gyver433_TX<2, 20> tx; void setup() { } @@ -34,4 +37,4 @@ void loop() { // отправка 10 раз в сек delay(100); -} \ No newline at end of file +} diff --git a/examples/isr_rx/isr_rx.ino b/examples/isr_rx/isr_rx.ino index 919cf02..9b1b7da 100644 --- a/examples/isr_rx/isr_rx.ino +++ b/examples/isr_rx/isr_rx.ino @@ -1,5 +1,5 @@ // приём в прерывании. Отправляет пример demo_tx -#define G433_SLOW_MODE +//#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с #include Gyver433_RX<2, 20> rx; // указали пин и размер буфера @@ -11,16 +11,16 @@ void setup() { } void isr() { - rx.tickISR(); // спец тикер вызывается в прерывании по CHANGE + rx.tickISR(); // спец. тикер вызывается в прерывании по CHANGE } void loop() { // .gotData() вернёт количество удачно принятых в прерывании байт - if (rx.gotData()) { + if (rx.gotData()) { // если больше 0 Serial.write(rx.buffer, rx.size); Serial.println(); } // имитация загруженного кода - delay(200); + delay(100); } diff --git a/examples/raw_rx/raw_rx.ino b/examples/raw_rx/raw_rx.ino index cdc4317..ac76d05 100644 --- a/examples/raw_rx/raw_rx.ino +++ b/examples/raw_rx/raw_rx.ino @@ -1,6 +1,6 @@ // обмен сырыми данными без CRC и буфера на отправку +// отправляет пример raw_tx -#define G433_SLOW_MODE #include Gyver433_RX<2, 20, G433_NOCRC> rx; // буфер на приём нужен! @@ -13,4 +13,4 @@ void loop() { Serial.write(rx.buffer, rx.size); Serial.println(); } -} \ No newline at end of file +} diff --git a/examples/raw_tx/raw_tx.ino b/examples/raw_tx/raw_tx.ino index 043327f..e6e1eb8 100644 --- a/examples/raw_tx/raw_tx.ino +++ b/examples/raw_tx/raw_tx.ino @@ -1,8 +1,10 @@ // обмен сырыми данными без CRC и буфера на отправку +// принимает пример raw_rx + +//#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с -#define G433_SLOW_MODE #include -Gyver433_TX<2, 0, G433_NOCRC> tx; +Gyver433_TX<2, 0, G433_NOCRC> tx; // буфер на отправку 0! Экономим void setup() { } diff --git a/examples/rx433_lcd/rx433_lcd.ino b/examples/rx433_lcd/rx433_lcd.ino index 3262288..bd14071 100644 --- a/examples/rx433_lcd/rx433_lcd.ino +++ b/examples/rx433_lcd/rx433_lcd.ino @@ -1,4 +1,5 @@ // выводим данные на дисплей. Отправляет пример demo_tx +//#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с #include Gyver433_RX<2> rx; // указали пин diff --git a/examples/rx433_struct/rx433_struct.ino b/examples/rx433_struct/rx433_struct.ino index 316cfef..c67da59 100644 --- a/examples/rx433_struct/rx433_struct.ino +++ b/examples/rx433_struct/rx433_struct.ino @@ -1,6 +1,7 @@ // приём структуры данных -#define G433_SLOW_MODE +//#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с + #include Gyver433_RX<2, 10> rx; // указали пин и размер буфера diff --git a/examples/tx433_struct/tx433_struct.ino b/examples/tx433_struct/tx433_struct.ino index 5c33d28..1bec95a 100644 --- a/examples/tx433_struct/tx433_struct.ino +++ b/examples/tx433_struct/tx433_struct.ino @@ -1,6 +1,8 @@ // передача структуры данных -#define G433_SLOW_MODE +//#define G433_SPEED 1000 // скорость 100-8000 бит/с, по умолч. 2000 бит/с +#define G433_SLOW // отправляю раз в секунду на SYN480R + #include Gyver433_TX<2, 10> tx; // указали пин и размер буфера @@ -25,7 +27,7 @@ void loop() { tx.sendData(data); - Serial.println("Transmit:"); + Serial.println("Transmitted:"); Serial.println(data.counter); Serial.println(data.randomNum); Serial.println(data.analog); diff --git a/keywords.txt b/keywords.txt index 47648b4..cb3b765 100644 --- a/keywords.txt +++ b/keywords.txt @@ -13,7 +13,9 @@ Gyver433_RX KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### sendData KEYWORD2 +sendDataSlow KEYWORD2 write KEYWORD2 +writeSlow KEYWORD2 tick KEYWORD2 tickISR KEYWORD2 tickWait KEYWORD2 @@ -31,5 +33,8 @@ G433_crc_xor KEYWORD2 G433_CRC8 LITERAL1 G433_XOR LITERAL1 G433_NOCRC LITERAL1 +G433_FAST LITERAL1 +G433_MEDIUM LITERAL1 +G433_SLOW LITERAL1 G433_SPEED LITERAL1 -G433_SLOW_MODE LITERAL1 \ No newline at end of file +G433_MANCHESTER LITERAL1 \ No newline at end of file diff --git a/library.properties b/library.properties index a48f5d0..6d6eee2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Gyver433 -version=1.1 +version=1.2 author=AlexGyver maintainer=AlexGyver sentence=Simple library for 433 MHz radio diff --git a/src/Gyver433.h b/src/Gyver433.h index 41ffe38..c1a9c02 100644 --- a/src/Gyver433.h +++ b/src/Gyver433.h @@ -3,10 +3,12 @@ Документация: GitHub: https://github.com/GyverLibs/Gyver433 Возможности: - - Не использует прерывания и таймеры (кроме нулевого, читает micros()) - - Встроенный CRC контроль целостности + - Супер лёгкая либа, заведётся даже на тини13 (отправка) + - Поддержка кривых китайских модулей + - Интерфейс Manchester или Pulselength + - Встроенный CRC контроль целостности (CRC8 или XOR) - Ускоренный алгоритм IO для AVR Arduino - - Работает с хорошими и плохими 433 МГц модулями + - Опционально работа в прерывании (приём данных) AlexGyver, alex@alexgyver.ru https://alexgyver.ru/ @@ -15,6 +17,7 @@ Версии: v1.0 - релиз v1.1 - оптимизация, новый интерфейс, поддержка дешёвых синих модулей, работа в прерывании + v1.2 - улучшение качества связи, оптимизация работы в прерывании */ #ifndef Gyver433_h @@ -22,43 +25,33 @@ #include #include "FastIO.h" -// настройки из скетча: -// #define G433_SLOW_MODE - включить "медленный режим" для плохих модулей -// #define G433_SPEED n - скорость, бит/сек. Рекомендуется 2000. Работает вплоть до 6000 - uint8_t G433_crc8(uint8_t *buffer, uint8_t size); // ручной CRC8 uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size); // ручной CRC XOR #define TRAINING_TIME_SLOW (500000ul) // время синхронизации для SLOW_MODE // ========================================================================= #ifndef G433_SPEED -#define G433_SPEED 3000 // скорость по умолчанию +#define G433_SPEED 2000 #endif // тайминги интерфейса -#define FRAME_TIME (1000000ul / G433_SPEED) // время фрейма -#define HALF_FRAME (FRAME_TIME / 2) // полфрейма -#define START_PULSE (FRAME_TIME * 2) // стартовый импульс -#define TRAINING_AMOUNT_SLOW (TRAINING_TIME_SLOW / FRAME_TIME / 2) // количество импульсов для SLOW_MODE +#define FRAME_TIME (1000000ul / G433_SPEED) // время фрейма (либо HIGH) +#define HALF_FRAME (FRAME_TIME / 2) // полфрейма (либо LOW) +#define START_PULSE (FRAME_TIME * 2) // стартовый импульс -// количество импульсов в зависимости от SLOW_MODE -#ifdef G433_SLOW_MODE -#define TRAINING_AMOUNT 40 -#else -#define TRAINING_AMOUNT 10 -#endif - -// окно времени для обработки старта и фрейма +// окно времени для обработки импульса #define START_MIN (START_PULSE * 3 / 4) #define START_MAX (START_PULSE * 5 / 4) #define FRAME_MIN (FRAME_TIME * 3 / 4) #define FRAME_MAX (FRAME_TIME * 5 / 4) +#define HALF_FRAME_MIN (HALF_FRAME * 3 / 4) +#define HALF_FRAME_MAX (HALF_FRAME * 5 / 4) // жоский delay для avr #ifdef AVR -#define G433_DELAY(x) _delay_us(x) +#define G433_DELAY _delay_us #else -#define G433_DELAY(x) delayMicroseconds(x) +#define G433_DELAY delayMicroseconds #endif // режимы CRC @@ -66,6 +59,17 @@ uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size); // ручной CRC XOR #define G433_XOR 1 #define G433_NOCRC 2 +// количество синхроимпульсов +#if defined(G433_FAST) +#define TRAINING_PULSES 10 +#elif defined(G433_MEDIUM) +#define TRAINING_PULSES 50 +#elif defined(G433_SLOW) +#define TRAINING_PULSES (TRAINING_TIME_SLOW / FRAME_TIME / 2) +#else +#define TRAINING_PULSES 50 +#endif + // crc8 один байт void G433_crc8_byte(uint8_t &crc, uint8_t data); @@ -95,188 +99,215 @@ public: // отправка сырого набора байтов void write(uint8_t* buf, uint16_t size) { - #ifdef G433_SLOW_MODE - for (uint16_t i = 0; i < ((millis() - tmr > 400) ? TRAINING_AMOUNT_SLOW : TRAINING_AMOUNT); i++) { - #else - for (uint16_t i = 0; i < TRAINING_AMOUNT; i++) { - #endif - fastWrite(TX_PIN, 1); - G433_DELAY(FRAME_TIME); - fastWrite(TX_PIN, 0); - G433_DELAY(FRAME_TIME); - } - fastWrite(TX_PIN, 1); // старт - G433_DELAY(START_PULSE); // ждём - fastWrite(TX_PIN, 0); // старт бит - G433_DELAY(HALF_FRAME); // ждём - for (uint16_t n = 0; n < size; n++) { - uint8_t data = buf[n]; - for (uint8_t b = 0; b < 8; b++) { - fastWrite(TX_PIN, !(data & 1)); - G433_DELAY(HALF_FRAME); - fastWrite(TX_PIN, (data & 1)); - G433_DELAY(HALF_FRAME); - data >>= 1; - } - } - fastWrite(TX_PIN, 0); // конец передачи - #ifdef G433_SLOW_MODE - tmr = millis(); - #endif + for (uint16_t i = 0; i < TRAINING_PULSES; i++) { + fastWrite(TX_PIN, 1); + G433_DELAY(FRAME_TIME); + fastWrite(TX_PIN, 0); + G433_DELAY(FRAME_TIME); } + fastWrite(TX_PIN, 1); // старт + G433_DELAY(START_PULSE); // ждём + fastWrite(TX_PIN, 0); // старт бит - // доступ к буферу - uint8_t buffer[TX_BUF]; - - private: - #ifdef G433_SLOW_MODE - uint32_t tmr = 0; - #endif - }; + #ifdef G433_MANCHESTER + G433_DELAY(HALF_FRAME); // ждём + for (uint16_t n = 0; n < size; n++) { + uint8_t data = buf[n]; + for (uint8_t b = 0; b < 8; b++) { + fastWrite(TX_PIN, !(data & 1)); + G433_DELAY(HALF_FRAME); + fastWrite(TX_PIN, (data & 1)); + G433_DELAY(HALF_FRAME); + data >>= 1; + } + } + fastWrite(TX_PIN, 0); // конец передачи + #else + bool flag = 0; + for (uint16_t n = 0; n < size; n++) { + uint8_t data = buf[n]; + for (uint8_t b = 0; b < 8; b++) { + if (data & 1) G433_DELAY(FRAME_TIME); + else G433_DELAY(HALF_FRAME); + fastWrite(TX_PIN, flag = !flag); + data >>= 1; + } + } + #endif + } + + // доступ к буферу + uint8_t buffer[TX_BUF]; + +private: +}; - // ============ ПРИЁМНИК ============ - template - class Gyver433_RX { - public: - Gyver433_RX() { - pinMode(RX_PIN, INPUT); - } - - // неблокирующий приём, вернёт кол-во успешно принятых байт - uint16_t tick() { - checkState(); - return checkEnd(); - } - - // tick для вызова в прерывании - void tickISR() { - checkState(); - } - - // блокирующий приём, вернёт кол-во успешно принятых байт - uint16_t tickWait() { - do { - if (tick()) return size; - } while (parse == 2); - return 0; - } - - // прочитает буфер в любой тип данных - template - bool readData(T &data) { - if (sizeof(T) > RX_BUF) return false; - uint8_t *ptr = (uint8_t*) &data; - for (uint16_t i = 0; i < sizeof(T); i++) *ptr++ = buffer[i]; - return true; - } - - // вернёт true при получении корректных данных - bool gotData() { - return checkEnd(); - } - - // получить размер принятых данных - uint16_t getSize() { +// ============ ПРИЁМНИК ============ +template +class Gyver433_RX { +public: + Gyver433_RX() { + pinMode(RX_PIN, INPUT); + } + + // неблокирующий приём, вернёт кол-во успешно принятых байт + uint16_t tick() { + if (pinChanged()) checkState(); + return gotData(); + } + + // tick для вызова в прерывании по CHANGE + void tickISR() { + #ifdef G433_MANCHESTER + if (pinChanged()) checkState(); + #else + checkState(); + #endif + } + + // блокирующий приём, вернёт кол-во успешно принятых байт + uint16_t tickWait() { + do { + if (tick()) return size; + } while (parse == 2); + return 0; + } + + // прочитает буфер в любой тип данных + template + bool readData(T &data) { + if (sizeof(T) > RX_BUF) return false; + uint8_t *ptr = (uint8_t*) &data; + for (uint16_t i = 0; i < sizeof(T); i++) *ptr++ = buffer[i]; + return true; + } + + // вернёт true при получении корректных данных + uint16_t gotData() { + if (parse == 2 && millis() - tmr2 >= 10) { // фрейм не закрыт + parse = size = 0; // приём окончен + if (byteCount > 1) { // если что то приняли + if (CRC_MODE == G433_CRC8) { // CRC8 + if (!G433_crc8(buffer, byteCount)) size = byteCount - 2; + } else if (CRC_MODE == G433_XOR) { // CRC XOR + if (!G433_crc_xor(buffer, byteCount)) size = byteCount - 2; + } else size = byteCount - 1; // без CRC + } return size; } - - // размер принятых данных - uint16_t size = 0; - - // доступ к буферу - uint8_t buffer[RX_BUF]; - - private: - void checkState() { - bool bit = fastRead(RX_PIN); // читаем пин - if (bit != prevBit) { // ловим изменение сигнала - uint32_t thisPulse = micros() - tmr; // время импульса - if (parse == 1) { // в прошлый раз поймали фронт - tmr += thisPulse; // сброс таймера - if (thisPulse > START_MIN && thisPulse < START_MAX) { // старт бит? - parse = 2; // ключ на старт - byteCount = bitCount = size = 0; // сброс - //dataReady = 0; - for (uint8_t i = 0; i < RX_BUF; i++) buffer[i] = 0; // чистим буфер - } else parse = 0; // не старт бит - } else if (parse == 2) { // идёт парсинг - if (thisPulse > FRAME_MIN && thisPulse < FRAME_MAX) { // фронт внутри таймфрейма - tmr += thisPulse; // синхронизируем тайминги - buffer[byteCount] >>= 1; // двигаем байт - if (bit && !prevBit) buffer[byteCount] |= _BV(7); // пишем единичку - bitCount++; // счётчик битов - } - if (bitCount == 8) { // собрали байт - bitCount = 0; // сброс - if (++byteCount >= RX_BUF) parse = 0; // буфер переполнен - } - } + return 0; + } + + // получить размер принятых данных + uint16_t getSize() { + return size; + } + + // размер принятых данных + uint16_t size = 0; + + // доступ к буферу + uint8_t buffer[RX_BUF]; + +private: + bool pinChanged() { + bit = fastRead(RX_PIN); + if (bit != prevBit) { + prevBit = bit; + return 1; + } return 0; + } - if (bit && !prevBit && parse == 0) { // ловим фронт - parse = 1; // флаг на старт - tmr += thisPulse; // сброс таймера - } - prevBit = bit; + void checkState() { + uint32_t thisPulse = micros() - tmr; // время импульса + if (parse == 1) { // в прошлый раз поймали фронт + #ifdef G433_MANCHESTER + tmr += thisPulse; // сброс таймера приёма + #endif + if (thisPulse > START_MIN && thisPulse < START_MAX) { // старт бит? + tmr2 = millis(); // сброс таймера активности + parse = 2; // ключ на старт + byteCount = bitCount = size = 0; // сброс + } else parse = 0; // не старт бит + } else if (parse == 2) { // идёт парсинг + #ifdef G433_MANCHESTER + if (thisPulse > FRAME_MIN && thisPulse < FRAME_MAX) { // фронт внутри таймфрейма + tmr += thisPulse; // синхронизируем тайминги + tmr2 = millis(); // сброс таймера активности + buffer[byteCount] >>= 1; // двигаем байт + buffer[byteCount] |= (bit << 7); // пишем данные + bitCount++; // счётчик битов } - } - uint16_t checkEnd() { - if (parse == 2 && micros() - tmr >= FRAME_TIME * 2) { // фрейм не закрыт - parse = size = 0; // приём окончен - if (byteCount > 1) { // если что то приняли - if (CRC_MODE == G433_CRC8) { // CRC8 - if (!G433_crc8(buffer, byteCount)) size = byteCount - 2; - } else if (CRC_MODE == G433_XOR) { // CRC XOR - if (!G433_crc_xor(buffer, byteCount)) size = byteCount - 2; - } else size = byteCount - 1; // без CRC - } - return size; + #else + uint8_t state = 2; + if (thisPulse > HALF_FRAME_MIN && thisPulse < HALF_FRAME_MAX) state = 0; // low бит + else if (thisPulse > FRAME_MIN && thisPulse < FRAME_MAX) state = 1; // high бит + if (state != 2) { + buffer[byteCount] >>= 1; // двигаем байт + buffer[byteCount] |= (state << 7); // пишем данные + bitCount++; // счётчик битов + tmr2 = millis(); // сброс таймера активности } - return 0; + #endif + if (bitCount == 8) { // собрали байт + bitCount = 0; // сброс + if (++byteCount >= RX_BUF) parse = 0; // буфер переполнен + } } - bool prevBit, dataReady = 0; - uint8_t parse = 0; - uint32_t tmr = 0; - uint8_t bitCount = 0, byteCount = 0; - }; + #ifdef G433_MANCHESTER + if (bit && parse == 0) { // ловим фронт + parse = 1; // флаг на старт + tmr += thisPulse; // сброс таймера + } + #else + if (parse == 0) parse = 1; // принудительно стартуем + tmr += thisPulse; // сброс таймера приёма + #endif + } + bool bit, prevBit; + uint8_t parse = 0; + uint32_t tmr = 0, tmr2 = 0; + uint8_t bitCount = 0, byteCount = 0; +}; - // ===== CRC ===== - void G433_crc8_byte(uint8_t &crc, uint8_t data) { +// ===== CRC ===== +void G433_crc8_byte(uint8_t &crc, uint8_t data) { #if defined (__AVR__) - // резкий алгоритм для AVR - uint8_t counter; - uint8_t buffer; - asm volatile ( - "EOR %[crc_out], %[data_in] \n\t" - "LDI %[counter], 8 \n\t" - "LDI %[buffer], 0x8C \n\t" - "_loop_start_%=: \n\t" - "LSR %[crc_out] \n\t" - "BRCC _loop_end_%= \n\t" - "EOR %[crc_out], %[buffer] \n\t" - "_loop_end_%=: \n\t" - "DEC %[counter] \n\t" - "BRNE _loop_start_%=" - : [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer) - : [crc_in]"0" (crc), [data_in]"r" (data) - ); + // резкий алгоритм для AVR + uint8_t counter; + uint8_t buffer; + asm volatile ( + "EOR %[crc_out], %[data_in] \n\t" + "LDI %[counter], 8 \n\t" + "LDI %[buffer], 0x8C \n\t" + "_loop_start_%=: \n\t" + "LSR %[crc_out] \n\t" + "BRCC _loop_end_%= \n\t" + "EOR %[crc_out], %[buffer] \n\t" + "_loop_end_%=: \n\t" + "DEC %[counter] \n\t" + "BRNE _loop_start_%=" + : [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer) + : [crc_in]"0" (crc), [data_in]"r" (data) + ); #else - // обычный для всех остальных - uint8_t i = 8; - while (i--) { - crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1); - data >>= 1; - } + // обычный для всех остальных + uint8_t i = 8; + while (i--) { + crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1); + data >>= 1; + } #endif - } +} - uint8_t G433_crc8(uint8_t *buffer, uint8_t size) { - uint8_t crc = 0; - for (uint8_t i = 0; i < size; i++) G433_crc8_byte(crc, buffer[i]); - return crc; - } - uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size) { - uint8_t crc = 0; - for (uint8_t i = 0; i < size; i++) crc ^= buffer[i]; - return crc; - } +uint8_t G433_crc8(uint8_t *buffer, uint8_t size) { + uint8_t crc = 0; + for (uint8_t i = 0; i < size; i++) G433_crc8_byte(crc, buffer[i]); + return crc; +} +uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size) { + uint8_t crc = 0; + for (uint8_t i = 0; i < size; i++) crc ^= buffer[i]; + return crc; +} #endif \ No newline at end of file