Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * irda.cpp
- *
- * Created: 04.10.2020 5:31:10
- * Author : Redfern89
- */
- #include "main.h"
- // Макросы для USART'а (использовал только при отладке и щас они нах ненужны)
- #define FOSC 16000000L
- #define BAUD 9600L
- #define MYUBRR FOSC / 16 / BAUD - 1
- #define T2_EN TCCR2 |= (1 << CS21)
- #define T2_STOP TCCR2 = 0x00
- volatile unsigned char NEC_DONE_FLAG = 0;
- volatile unsigned char SCLK = 0;
- volatile unsigned char NEC_RECV_CNT = 0;
- volatile unsigned char NEC_START_FLAG = 0;
- volatile unsigned char NEC_REPEAT_FLAG = 0;
- volatile unsigned char NEC_REPEAT_WORK = 0;
- volatile unsigned long int command = 0x00000000;
- volatile unsigned char necAddr1 = 0x00;
- volatile unsigned char necAddr2 = 0x00;
- volatile unsigned char necCmd1 = 0x00;
- volatile unsigned char necCmd2 = 0x00;
- #define bitRead(value, bit) (((value) >> (bit)) & 0x01)
- #define bitSet(value, bit) ((value) |= (1UL << (bit)))
- #define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
- #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
- #define bytesJoin(value, b1, b2, b3, b4) value = b1; value <<= 8UL; value |= b2; value <<= 8UL; value |= b3; value <<= 8UL; value |= b4;
- // Иницмализация UART. Справедливо только для ATmega8
- void USORT_Init(unsigned char ubrr) {
- UBRRH = (unsigned char)(ubrr >> 8);
- UBRRL = (unsigned char)ubrr;
- UCSRB = (0 << RXEN) | (1 << TXEN);
- UCSRC = (1 << USBS) | (3 << UCSZ0) | (1 << URSEL);
- }
- // Отправка по UART. Справедливо только для ATmega8
- void USORT_Transmit( unsigned char data ) {
- while ( !( UCSRA & (1 << UDRE)) );
- UDR = data;
- }
- // Отправка строки через UART
- void USORT_Strring(char *stringPtr){
- while(*stringPtr != 0) {
- USORT_Transmit(*stringPtr);
- stringPtr++;
- }
- }
- // Вход в прерывание 2го таймера по переполнению. каждые 100мкс
- ISR (TIMER2_OVF_vect) {
- TCNT2 = 0x38; // это мы уже сто раз проходили
- if (++SCLK >= 1200) { // Отсчитываем переменную SCLK каждые 100мкс
- // А при достижении какого либо порога - все сбрасываем
- T2_STOP;
- NEC_START_FLAG = 0;
- NEC_RECV_CNT = 0;
- command = 0x00000000;
- necAddr1 = 0x00;
- necAddr2 = 0x00;
- necCmd1 = 0x00;
- necCmd2 = 0x00;
- }
- }
- // Вход во внешнее прерывание
- ISR (INT0_vect) {
- T2_EN; // Как поймали первый спадающий фронт - запускаем таймер
- if (SCLK > 5) { // Все, что меньше 5 не обрабатываем
- // Стартовый импульс вместе с опорным длятся 13.2мс
- if (SCLK >= 132 && SCLK <= 134) {
- NEC_START_FLAG = 1;
- NEC_RECV_CNT = 0;
- NEC_REPEAT_WORK = 0;
- }
- // Если поймали правильный стартовый импульс - можем начать дальнейшую обработку
- if (NEC_START_FLAG) {
- // Повторы в NEC дляться 11мс
- if (SCLK >= 110 && SCLK <= 112) {
- NEC_REPEAT_FLAG = 1;
- NEC_REPEAT_WORK = 1;
- }
- /* Знаю, по-идиотски, но умнее лень было придумывать */
- if (SCLK >= 10 && SCLK <= 12) { // Длительность лог. 0 - 11мс
- NEC_RECV_CNT++; // Прибавляем счетчик принятых данных
- /* тут просто все распихиваем по переменным */
- if (NEC_RECV_CNT >= 0 && NEC_RECV_CNT < 9) necAddr1 &= ~(1 << NEC_RECV_CNT);
- if (NEC_RECV_CNT >= 9 && NEC_RECV_CNT < 17) necAddr2 &= ~(1 << (NEC_RECV_CNT - 9));
- if (NEC_RECV_CNT >= 17 && NEC_RECV_CNT < 25) necCmd1 &= ~(1 << (NEC_RECV_CNT - 17));
- if (NEC_RECV_CNT >= 25 && NEC_RECV_CNT < 33) necCmd2 &= ~(1 << (NEC_RECV_CNT - 25));
- }
- if (SCLK >= 20 && SCLK <= 24) { // Длительность лог. 1 - 22 мс
- /* Тут все то-же самое, что и с нулями */
- NEC_RECV_CNT++;
- if (NEC_RECV_CNT >= 0 && NEC_RECV_CNT < 9) necAddr1 |= (1 << NEC_RECV_CNT);
- if (NEC_RECV_CNT >= 9 && NEC_RECV_CNT < 17) necAddr2 |= (1 << (NEC_RECV_CNT - 9));
- if (NEC_RECV_CNT >= 17 && NEC_RECV_CNT < 25) necCmd1 |= (1 << (NEC_RECV_CNT - 17));
- if (NEC_RECV_CNT >= 25 && NEC_RECV_CNT < 33) necCmd2 |= (1 << (NEC_RECV_CNT - 25));
- }
- // Как только чтение 32х бит завершеноы
- if (NEC_RECV_CNT == 32) {
- // Проверяем на целостность принятых данных
- // В первой версии протокола оба адреса и команды идут как прмые, так и инверсные
- // Во второй версии адрес занимает два байта и не имеет инверсии
- // Собсно сложив прямые с нверсными байты и получив на выходе FFh - мы понимаем, что все целехонькое
- if ((((necAddr1 + necAddr2) == 0xFF) && ((necCmd1 + necCmd2) == 0xff)) || ((necCmd1 + necCmd2) == 0xFF)) {
- NEC_DONE_FLAG = 1;
- NEC_RECV_CNT = 0;
- bytesJoin(command, necAddr1, necAddr2, necCmd1, necCmd2);// Склеиваем все в одну команду
- }
- T2_STOP; // Останавливаем подсчет
- }
- }
- }
- SCLK = 0; // Обнуляем текущий счетчик
- }
- int main(void) {
- asm("CLI");
- // Инициализируем UART
- USORT_Init(MYUBRR);
- T2_STOP; // Остановка таймера 2
- TIMSK |= (1 << TOIE2); // Настраиваем таймер 2 на переполнение
- // (TIMER_RESOLUTION - (mks * (F_CPU / Prescaler) / 1000000))
- TCNT2 = 0x38; // Переполнение каждые 100мкс
- // Настройка внешнего прерывание на спад фронта
- MCUCR |= (1 << ISC01) | (0 << ISC00);
- GICR |= (1 << INT0);
- asm("SEI");
- while (1) {
- if (NEC_DONE_FLAG || NEC_REPEAT_FLAG) { // Если пришла команда или повтор команды
- // Уже нет
- NEC_DONE_FLAG = 0;
- NEC_REPEAT_FLAG = 0;
- // Клавиша POWER без обработки повтора
- if (command == 0x00ff45ba && !NEC_REPEAT_WORK) {
- USORT_Transmit(0xFF);
- }
- // Клавиша PLUS с обработкой повтора
- if (command == 0x00FF40BF && NEC_REPEAT_WORK) {
- USORT_Transmit(0x00);
- }
- // USORT_Transmit((command >> 24UL) & 0xFF);
- // USORT_Transmit((command >> 16UL) & 0xFF);
- // USORT_Transmit((command >> 8UL) & 0xFF);
- // USORT_Transmit(command & 0xFF);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment