Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * main.c
- *
- * Created: 13.01.2019 19:24:51
- * Author : Redfern.89
- */
- // Частота проца в герцах
- #ifndef F_CPU
- #define F_CPU 16000000UL
- #endif
- // Системные инклюцы
- #include <avr/io.h>
- #include <avr/interrupt.h>
- // Запуск и стоп таймера 0
- #define T0_START { TCCR0B |= (1 << CS01) | (1 << CS00); }
- #define T0_STOP { TCCR0B = 0x00; }
- // Макросы для USART'а
- #define FOSC 16000000L
- #define BAUD 9600L
- #define MYUBRR FOSC / 16 / BAUD -1
- // Кое-какие глобальные переменные
- const int NEC_MAX_RESET_OVF = 1200; // Столько тиков должно пройти, что-бы система перешла вновь в режим ожидания (1200 * 64 = 76.8ms)
- volatile int NEC_SCLK = 0; // Тактовые синхроимпульсы 64us
- volatile int NEC_START_FLAG = 0; // Говорит о том, что пришло стартовое сообщение
- volatile int NEC_REPEAT_FLAG = 0; // Говорит о том, что идет повтор сообщения (не используется)
- volatile int NEC_RECV_CNT = 0; // Сколько бит принято при обнаружении
- volatile unsigned char addr1 = 0x00; // Адрес
- volatile unsigned char addr2 = 0x00; // Инверсия адреса
- volatile unsigned char cmd1 = 0x00; // Команда
- volatile unsigned char cmd2 = 0x00; // Инверсия команды
- const int NEC_PACKET_LENGTH = 32; // Длина пакета
- /*
- Минимальные м максимальные интервалы. Значения были вычесленны при 100 нажатиях на кнопки пульта,
- полученные значения были запёханы в массив и найдены минимумы и максимумы
- */
- const int NEC_MIN_HEADER_MESSAGE_CLK = 200;
- const int NEC_MAX_HEADER_MESSAGE_CLK = 235;
- const int NEC_MIN_ONE_BIT_CLK = 33;
- const int NEC_MAX_ONE_BIT_CLK = 38;
- const int NEC_MIN_NUL_BIT_CLK = 17;
- const int NEC_MAX_NUL_BIT_CLK = 20;
- // Это смещения в битах. Нужно для определения позиции следующего байта
- const int offset1_addr1 = 0;
- const int offset2_addr1 = 9;
- const int offset1_addr2 = 9;
- const int offset2_addr2 = 17;
- const int offset1_cmd1 = 17;
- const int offset2_cmd1 = 25;
- const int offset1_cmd2 = 25;
- const int offset2_cmd2 = 33;
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- USART functions
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- void USORT_Init(unsigned char ubrr){
- UBRR0H = (unsigned char)(ubrr >> 8);
- UBRR0L = (unsigned char)ubrr;
- UCSR0B = (1 << RXEN0) | (1 << TXEN0);
- UCSR0C = (1 << USBS0) | (3 << UCSZ00);
- }
- void USORT_Transmit( unsigned char data ) {
- while ( !( UCSR0A & (1 << UDRE0)) );
- UDR0 = data;
- }
- // Вход в прерывание по переполнению таймера
- ISR (TIMER0_OVF_vect) {
- TCNT0 = 0xF0;
- // Вот тут мы переходим в ожидание следующей команды
- if (++NEC_SCLK >= NEC_MAX_RESET_OVF) {
- T0_STOP;
- NEC_SCLK = 0;
- NEC_START_FLAG = 0;
- TCNT0 = 0xF0;
- }
- }
- // Вход во внешнее прерывание
- SIGNAL (INT0_vect) {
- T0_START; // Начинаем отсчет
- if (NEC_SCLK > 0) { // Первое значение приходит нулевым. нахуй его, пропускаем и идем дальше
- // Тут определяем стартовое сообщение (преамбулу)
- if (NEC_SCLK >= NEC_MIN_HEADER_MESSAGE_CLK && NEC_SCLK < NEC_MAX_HEADER_MESSAGE_CLK) {
- NEC_START_FLAG = 1;
- NEC_REPEAT_FLAG = 0;
- }
- // Тут определяем биты нулевого значения
- if ((NEC_SCLK >= NEC_MIN_NUL_BIT_CLK && NEC_SCLK < NEC_MAX_NUL_BIT_CLK) && NEC_START_FLAG) {
- NEC_RECV_CNT++; // Инкрементируем колличество принятых нулей
- // ну а тут мутнаые процедуры записи значений в переменные
- if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) {
- addr1 &= ~(1 << (NEC_RECV_CNT - offset1_addr1));
- }
- if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
- addr2 &= ~(1 << (NEC_RECV_CNT - offset1_addr2));
- }
- if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
- cmd1 &= ~(1 << (NEC_RECV_CNT - offset1_cmd1));
- }
- if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
- cmd2 &= ~(1 << (NEC_RECV_CNT - offset1_cmd2));
- }
- }
- // Тут определяем биты положительного значения
- if ((NEC_SCLK >= NEC_MIN_ONE_BIT_CLK && NEC_SCLK < NEC_MAX_ONE_BIT_CLK) && NEC_START_FLAG) {
- NEC_RECV_CNT++; // Инкрементируем колличество принятых едениц
- if (NEC_RECV_CNT >= offset1_addr1 && NEC_RECV_CNT < offset2_addr1) {
- addr1 |= (1 << (NEC_RECV_CNT - offset1_addr1));
- }
- if (NEC_RECV_CNT >= offset1_addr2 && NEC_RECV_CNT < offset2_addr2) {
- addr2 |= (1 << (NEC_RECV_CNT - offset1_addr2));
- }
- if (NEC_RECV_CNT >= offset1_cmd1 && NEC_RECV_CNT < offset2_cmd1) {
- cmd1 |= (1 << (NEC_RECV_CNT - offset1_cmd1));
- }
- if (NEC_RECV_CNT >= offset1_cmd2 && NEC_RECV_CNT < offset2_cmd2) {
- cmd2 |= (1 << (NEC_RECV_CNT - offset1_cmd2));
- }
- }
- // Тут обнуляем счетчик синхроимульсов, что-бы отсчитывать время следующего прерывания с нуля
- NEC_SCLK = 0;
- // Колличество нулей и едениц в конечном счете должно быть 32, на этом и остановимся
- if (NEC_RECV_CNT == NEC_PACKET_LENGTH) {
- // Выставляем в стартовое положение все счетчики и останавлиеваем подсчет
- T0_STOP;
- NEC_RECV_CNT = 0;
- TCNT0 = 0xF0;
- // Проверка на целостность сообщения
- if ((addr1 + addr2 == 0xFF) && (cmd1 + cmd2) == 0xFF) {
- // Тестовый вывод в UART
- USORT_Transmit(addr1);
- USORT_Transmit(addr2);
- USORT_Transmit(cmd1);
- USORT_Transmit(cmd2);
- }
- }
- }
- }
- int main(void) {
- asm("CLI");
- // Инициализация внешнего прерывания (на спад)
- EICRA |= (1 << ISC01) | (0 << ISC00);
- EIMSK |= (1 << INT0);
- EIFR |= (1 << INTF0);
- PCICR = 0x00;
- // Инициализация таймера/счестчика 0 для подсчета временного интервала между импульсами
- TCCR0B = 0x00;//(1 << CS00) | (1 << CS01);
- TIMSK0 |= (1 << TOIE0);
- TCNT0 = 0xF0;
- USORT_Init(MYUBRR);
- asm("SEI");
- while (1) {
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment