Redfern_89

IRDA_NEC.cpp

Oct 6th, 2020 (edited)
916
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.73 KB | None | 0 0
  1. /*
  2.  * irda.cpp
  3.  *
  4.  * Created: 04.10.2020 5:31:10
  5.  * Author : Redfern89
  6.  */
  7. #include "main.h"
  8.  
  9.  
  10. // Макросы для USART'а (использовал только при отладке и щас они нах ненужны)
  11. #define FOSC 16000000L
  12. #define BAUD 9600L
  13. #define MYUBRR FOSC / 16 / BAUD - 1
  14.  
  15. #define T2_EN TCCR2 |= (1 << CS21)
  16. #define T2_STOP TCCR2 = 0x00
  17. volatile unsigned char NEC_DONE_FLAG = 0;
  18. volatile unsigned char SCLK = 0;
  19. volatile unsigned char NEC_RECV_CNT = 0;
  20. volatile unsigned char NEC_START_FLAG = 0;
  21. volatile unsigned char NEC_REPEAT_FLAG = 0;
  22. volatile unsigned char NEC_REPEAT_WORK = 0;
  23. volatile unsigned long int command = 0x00000000;
  24. volatile unsigned char necAddr1 = 0x00;
  25. volatile unsigned char necAddr2 = 0x00;
  26. volatile unsigned char necCmd1 = 0x00;
  27. volatile unsigned char necCmd2 = 0x00;
  28.  
  29. #define bitRead(value, bit) (((value) >> (bit)) & 0x01)
  30. #define bitSet(value, bit) ((value) |= (1UL << (bit)))
  31. #define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
  32. #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
  33.  
  34. #define bytesJoin(value, b1, b2, b3, b4) value = b1; value <<= 8UL; value |= b2; value <<= 8UL; value |= b3; value <<= 8UL; value |= b4;
  35.  
  36. // Иницмализация UART. Справедливо только для ATmega8
  37. void USORT_Init(unsigned char ubrr) {
  38.     UBRRH = (unsigned char)(ubrr >> 8);
  39.     UBRRL = (unsigned char)ubrr;
  40.     UCSRB = (0 << RXEN) | (1 << TXEN);
  41.     UCSRC = (1 << USBS) | (3 << UCSZ0) | (1 << URSEL);
  42. }
  43.  
  44. // Отправка по UART. Справедливо только для ATmega8
  45. void USORT_Transmit( unsigned char data ) {
  46.     while ( !( UCSRA & (1 << UDRE)) );
  47.     UDR = data;
  48. }
  49.  
  50. // Отправка строки через UART
  51. void USORT_Strring(char *stringPtr){
  52.     while(*stringPtr != 0) {
  53.         USORT_Transmit(*stringPtr);
  54.         stringPtr++;
  55.     }
  56. }
  57.  
  58. // Вход в прерывание 2го таймера по переполнению. каждые 100мкс
  59. ISR (TIMER2_OVF_vect) {
  60.     TCNT2 = 0x38; // это мы уже сто раз проходили
  61.     if (++SCLK >= 1200) { // Отсчитываем переменную SCLK каждые 100мкс
  62.         // А при достижении какого либо порога - все сбрасываем
  63.         T2_STOP;
  64.         NEC_START_FLAG = 0;
  65.         NEC_RECV_CNT = 0;
  66.         command = 0x00000000;
  67.         necAddr1 = 0x00;
  68.         necAddr2 = 0x00;
  69.         necCmd1 = 0x00;
  70.         necCmd2 = 0x00;
  71.     }
  72. }
  73.  
  74. // Вход во внешнее прерывание
  75. ISR (INT0_vect) {
  76.     T2_EN; // Как поймали первый спадающий фронт - запускаем таймер
  77.     if (SCLK > 5) { // Все, что меньше 5 не обрабатываем
  78.         // Стартовый импульс вместе с опорным длятся 13.2мс
  79.         if (SCLK >= 132 && SCLK <= 134) {
  80.             NEC_START_FLAG = 1;
  81.             NEC_RECV_CNT = 0;
  82.             NEC_REPEAT_WORK = 0;
  83.         }
  84.         // Если поймали правильный стартовый импульс - можем начать дальнейшую обработку
  85.         if (NEC_START_FLAG) {
  86.             // Повторы в NEC дляться 11мс
  87.             if (SCLK >= 110 && SCLK <= 112) {
  88.                 NEC_REPEAT_FLAG = 1;
  89.                 NEC_REPEAT_WORK = 1;
  90.             }
  91.             /* Знаю, по-идиотски, но умнее лень было придумывать */
  92.             if (SCLK >= 10 && SCLK <= 12) { // Длительность лог. 0 - 11мс
  93.                 NEC_RECV_CNT++; // Прибавляем счетчик принятых данных
  94.                 /* тут просто все распихиваем по переменным */
  95.                 if (NEC_RECV_CNT >= 0 && NEC_RECV_CNT < 9) necAddr1 &= ~(1 << NEC_RECV_CNT);
  96.                 if (NEC_RECV_CNT >= 9 && NEC_RECV_CNT < 17) necAddr2 &= ~(1 << (NEC_RECV_CNT - 9));
  97.                 if (NEC_RECV_CNT >= 17 && NEC_RECV_CNT < 25) necCmd1 &= ~(1 << (NEC_RECV_CNT - 17));
  98.                 if (NEC_RECV_CNT >= 25 && NEC_RECV_CNT < 33) necCmd2 &= ~(1 << (NEC_RECV_CNT - 25));
  99.             }
  100.        
  101.             if (SCLK >= 20 && SCLK <= 24) { // Длительность лог. 1 - 22 мс
  102.                 /* Тут все то-же самое, что и с нулями */
  103.                 NEC_RECV_CNT++;
  104.                 if (NEC_RECV_CNT >= 0 && NEC_RECV_CNT < 9) necAddr1 |= (1 << NEC_RECV_CNT);
  105.                 if (NEC_RECV_CNT >= 9 && NEC_RECV_CNT < 17) necAddr2 |= (1 << (NEC_RECV_CNT - 9));
  106.                 if (NEC_RECV_CNT >= 17 && NEC_RECV_CNT < 25) necCmd1 |= (1 << (NEC_RECV_CNT - 17));
  107.                 if (NEC_RECV_CNT >= 25 && NEC_RECV_CNT < 33) necCmd2 |= (1 << (NEC_RECV_CNT - 25));
  108.             }
  109.        
  110.             // Как только чтение 32х бит завершеноы
  111.             if (NEC_RECV_CNT == 32) {
  112.                 // Проверяем на целостность принятых данных
  113.                 // В первой версии протокола оба адреса и команды идут как прмые, так и инверсные
  114.                 // Во второй версии адрес занимает два байта и не имеет инверсии
  115.                 // Собсно сложив прямые с нверсными байты и получив на выходе FFh - мы понимаем, что все целехонькое
  116.                 if ((((necAddr1 + necAddr2) == 0xFF) && ((necCmd1 + necCmd2) == 0xff)) || ((necCmd1 + necCmd2) == 0xFF)) {
  117.                     NEC_DONE_FLAG = 1;
  118.                     NEC_RECV_CNT = 0;
  119.                     bytesJoin(command, necAddr1, necAddr2, necCmd1, necCmd2);// Склеиваем все в одну команду
  120.                 }
  121.                 T2_STOP; // Останавливаем подсчет
  122.             }
  123.        
  124.         }
  125.     }
  126.    
  127.     SCLK = 0; // Обнуляем текущий счетчик
  128.  
  129. }
  130.  
  131. int main(void) {
  132.     asm("CLI");
  133.    
  134.     // Инициализируем UART
  135.     USORT_Init(MYUBRR);
  136.    
  137.     T2_STOP; // Остановка таймера 2
  138.     TIMSK |= (1 << TOIE2); // Настраиваем таймер 2 на переполнение
  139.    
  140.     // (TIMER_RESOLUTION - (mks * (F_CPU / Prescaler) / 1000000))
  141.     TCNT2 = 0x38; // Переполнение каждые 100мкс
  142.    
  143.     // Настройка внешнего прерывание на спад фронта
  144.     MCUCR |= (1 << ISC01) | (0 << ISC00);
  145.     GICR |= (1 << INT0);
  146.    
  147.     asm("SEI");
  148.    
  149.     while (1) {
  150.         if (NEC_DONE_FLAG || NEC_REPEAT_FLAG) { // Если пришла команда или повтор команды
  151.             // Уже нет
  152.             NEC_DONE_FLAG = 0;
  153.             NEC_REPEAT_FLAG = 0;
  154.            
  155.             // Клавиша POWER без обработки повтора
  156.             if (command == 0x00ff45ba && !NEC_REPEAT_WORK) {
  157.                 USORT_Transmit(0xFF);
  158.             }
  159.             // Клавиша PLUS с обработкой повтора
  160.             if (command == 0x00FF40BF && NEC_REPEAT_WORK) {
  161.                 USORT_Transmit(0x00);  
  162.             }
  163. //          USORT_Transmit((command >> 24UL) & 0xFF);
  164. //          USORT_Transmit((command >> 16UL) & 0xFF);
  165. //          USORT_Transmit((command >> 8UL) & 0xFF);
  166. //          USORT_Transmit(command & 0xFF);
  167.  
  168.         }
  169.  
  170.     }
  171. }
  172.  
  173.  
Advertisement
Add Comment
Please, Sign In to add comment