Redfern_89

[AVR] nec.c

Jan 13th, 2019
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.89 KB | None | 0 0
  1. /*
  2.  * main.c
  3.  *
  4.  * Created: 13.01.2019 19:24:51
  5.  * Author : Redfern.89
  6.  */
  7.  
  8. // Частота проца в герцах
  9. #ifndef F_CPU
  10. #define F_CPU   16000000UL
  11. #endif
  12.  
  13. // Системные инклюцы
  14. #include <avr/io.h>
  15. #include <avr/interrupt.h>
  16.  
  17. // Запуск и стоп таймера 0
  18. #define T0_START    {    TCCR0B |= (1 << CS01) | (1 << CS00);   }
  19. #define T0_STOP     {    TCCR0B = 0x00;                         }
  20.  
  21. // Макросы для USART'а
  22. #define FOSC 16000000L
  23. #define BAUD 9600L
  24. #define MYUBRR FOSC / 16 / BAUD -1
  25.    
  26. // Кое-какие глобальные переменные
  27. const int NEC_MAX_RESET_OVF = 1200; // Столько тиков должно пройти, что-бы система перешла вновь в режим ожидания (1200 * 64 = 76.8ms)
  28. volatile int NEC_SCLK = 0;          // Тактовые синхроимпульсы 64us
  29. volatile int NEC_START_FLAG = 0;    // Говорит о том, что пришло стартовое сообщение
  30. volatile int NEC_REPEAT_FLAG = 0;   // Говорит о том, что идет повтор сообщения (не используется)
  31. volatile int NEC_RECV_CNT = 0;      // Сколько бит принято при обнаружении
  32. volatile unsigned char addr1 = 0x00;    // Адрес
  33. volatile unsigned char addr2 = 0x00;    // Инверсия адреса
  34. volatile unsigned char cmd1 = 0x00;     // Команда
  35. volatile unsigned char cmd2 = 0x00;     // Инверсия команды
  36. const int NEC_PACKET_LENGTH = 32;       // Длина пакета
  37. /*
  38.     Минимальные м максимальные интервалы. Значения были вычесленны при 100 нажатиях на кнопки пульта,
  39.     полученные значения были запёханы в массив и найдены минимумы и максимумы
  40. */
  41. const int NEC_MIN_HEADER_MESSAGE_CLK = 200;
  42. const int NEC_MAX_HEADER_MESSAGE_CLK = 235;
  43. const int NEC_MIN_ONE_BIT_CLK = 33;
  44. const int NEC_MAX_ONE_BIT_CLK = 38;
  45. const int NEC_MIN_NUL_BIT_CLK = 17;
  46. const int NEC_MAX_NUL_BIT_CLK = 20;
  47. // Это смещения в битах. Нужно для определения позиции следующего байта
  48. const int offset1_addr1 = 0;
  49. const int offset2_addr1 = 9;
  50. const int offset1_addr2 = 9;
  51. const int offset2_addr2 = 17;
  52. const int offset1_cmd1 = 17;
  53. const int offset2_cmd1 = 25;
  54. const int offset1_cmd2 = 25;
  55. const int offset2_cmd2 = 33;
  56.    
  57. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  58.                                 USART functions
  59.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  60. void USORT_Init(unsigned char ubrr){
  61.     UBRR0H = (unsigned char)(ubrr >> 8);
  62.     UBRR0L = (unsigned char)ubrr;
  63.     UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  64.     UCSR0C = (1 << USBS0) | (3 << UCSZ00);
  65. }
  66.  
  67. void USORT_Transmit( unsigned char data ) {
  68.     while ( !( UCSR0A & (1 << UDRE0)) );
  69.     UDR0 = data;
  70. }
  71.    
  72. // Вход в прерывание по переполнению таймера
  73. ISR (TIMER0_OVF_vect) {
  74.     TCNT0 = 0xF0;
  75.     // Вот тут мы переходим в ожидание следующей команды
  76.     if (++NEC_SCLK >= NEC_MAX_RESET_OVF) {
  77.         T0_STOP;
  78.         NEC_SCLK = 0;
  79.         NEC_START_FLAG = 0;
  80.         TCNT0 = 0xF0;
  81.     }
  82. }
  83.  
  84. // Вход во внешнее прерывание
  85. SIGNAL (INT0_vect) {
  86.     T0_START; // Начинаем отсчет
  87.    
  88.     if (NEC_SCLK > 0) { // Первое значение приходит нулевым. нахуй его, пропускаем и идем дальше
  89.        
  90.         // Тут определяем стартовое сообщение (преамбулу)
  91.         if (NEC_SCLK >= NEC_MIN_HEADER_MESSAGE_CLK && NEC_SCLK < NEC_MAX_HEADER_MESSAGE_CLK) {
  92.             NEC_START_FLAG = 1;
  93.             NEC_REPEAT_FLAG = 0;
  94.         }
  95.        
  96.         // Тут определяем биты нулевого значения
  97.         if ((NEC_SCLK >= NEC_MIN_NUL_BIT_CLK && NEC_SCLK < NEC_MAX_NUL_BIT_CLK) && NEC_START_FLAG) {
  98.             NEC_RECV_CNT++; // Инкрементируем колличество принятых нулей
  99.             // ну а тут мутнаые процедуры записи значений в переменные
  100.             if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) {
  101.                 addr1 &= ~(1 << (NEC_RECV_CNT - offset1_addr1));
  102.             }
  103.             if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
  104.                 addr2 &= ~(1 << (NEC_RECV_CNT - offset1_addr2));
  105.             }
  106.             if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
  107.                 cmd1 &= ~(1 << (NEC_RECV_CNT - offset1_cmd1));
  108.             }
  109.             if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
  110.                 cmd2 &= ~(1 << (NEC_RECV_CNT - offset1_cmd2));
  111.             }
  112.         }
  113.        
  114.         // Тут определяем биты положительного значения
  115.         if ((NEC_SCLK >= NEC_MIN_ONE_BIT_CLK && NEC_SCLK < NEC_MAX_ONE_BIT_CLK) && NEC_START_FLAG) {
  116.             NEC_RECV_CNT++; // Инкрементируем колличество принятых едениц
  117.            
  118.             if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) {
  119.                 addr1 |= (1 << (NEC_RECV_CNT - offset1_addr1));
  120.             }
  121.             if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
  122.                 addr2 |= (1 << (NEC_RECV_CNT - offset1_addr2));
  123.             }
  124.             if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
  125.                 cmd1 |= (1 << (NEC_RECV_CNT - offset1_cmd1));
  126.             }
  127.             if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
  128.                 cmd2 |= (1 << (NEC_RECV_CNT - offset1_cmd2));
  129.             }
  130.         }
  131.        
  132.         // Тут обнуляем счетчик синхроимульсов, что-бы отсчитывать время следующего прерывания с нуля
  133.         NEC_SCLK = 0;
  134.        
  135.         // Колличество нулей и едениц в конечном счете должно быть 32, на этом и остановимся
  136.         if (NEC_RECV_CNT == NEC_PACKET_LENGTH) {
  137.             // Выставляем в стартовое положение все счетчики и останавлиеваем подсчет
  138.             T0_STOP;
  139.             NEC_RECV_CNT = 0;
  140.             TCNT0 = 0xF0;
  141.            
  142.             // Проверка на целостность сообщения
  143.             if ((addr1 + addr2 == 0xFF) && (cmd1 + cmd2) == 0xFF) {
  144.                 // Тестовый вывод в UART
  145.                 USORT_Transmit(addr1);
  146.                 USORT_Transmit(addr2);
  147.                 USORT_Transmit(cmd1);
  148.                 USORT_Transmit(cmd2);
  149.             }
  150.         }
  151.    
  152.     }
  153. }
  154.  
  155. int main(void) {
  156.     asm("CLI");
  157.    
  158.     // Инициализация внешнего прерывания (на спад)
  159.     EICRA |= (1 << ISC01) | (0 << ISC00);
  160.     EIMSK |= (1 << INT0);
  161.     EIFR |= (1 << INTF0);
  162.     PCICR = 0x00;
  163.        
  164.     // Инициализация таймера/счестчика 0 для подсчета временного интервала между импульсами
  165.     TCCR0B = 0x00;//(1 << CS00) | (1 << CS01);
  166.     TIMSK0 |= (1 << TOIE0);
  167.     TCNT0 = 0xF0;
  168.        
  169.     USORT_Init(MYUBRR);
  170.    
  171.     asm("SEI");
  172.    
  173.     while (1)  {
  174.  
  175.     }
  176.    
  177.     return 0;
  178. }
Advertisement
Add Comment
Please, Sign In to add comment