From f79e8baa103ced7b57d1ce1bf9b705914f131a34 Mon Sep 17 00:00:00 2001 From: Alexey 'Cluster' Avdyukhin Date: Mon, 9 Sep 2013 17:11:28 +0400 Subject: New CLUNET, UTF-8 translation --- clunet.c | 138 ++++++++++++++++++++++++++++++-------------------------- clunet.h | 112 +++++++++++++++++++++++---------------------- clunet_config.h | 3 +- intercom.c | 120 ++++++++++++++++++++++++------------------------ 4 files changed, 193 insertions(+), 180 deletions(-) diff --git a/clunet.c b/clunet.c index 3288fd9..1c00e58 100644 --- a/clunet.c +++ b/clunet.c @@ -1,7 +1,7 @@ /* Name: clunet.c * Project: CLUNET network driver * Author: Alexey Avdyukhin - * Creation Date: 2013-07-22 + * Creation Date: 2013-09-09 * License: DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE */ @@ -26,7 +26,7 @@ volatile unsigned char clunetReadingCurrentBit; volatile unsigned char clunetCurrentPrio; volatile unsigned char clunetReceivingState = 0; -volatile unsigned char clunetReceivingPrio = 0; +//volatile unsigned char clunetReceivingPrio = 0; volatile unsigned char clunetTimerStart = 0; volatile unsigned char clunetTimerPeriods = 0; @@ -55,73 +55,73 @@ char check_crc(char* data, unsigned char size) ISR(CLUNET_TIMER_COMP_VECTOR) { - unsigned char now = CLUNET_TIMER_REG; // + unsigned char now = CLUNET_TIMER_REG; // Запоминаем текущее время switch (clunetSendingState) { - case CLUNET_SENDING_STATE_PREINIT: // + case CLUNET_SENDING_STATE_PREINIT: // Нужно подождать перед отправкой CLUNET_TIMER_REG_OCR = now + CLUNET_T; - clunetSendingState = CLUNET_SENDING_STATE_INIT; // + clunetSendingState = CLUNET_SENDING_STATE_INIT; // Начинаем следующую фазу return; - case CLUNET_SENDING_STATE_STOP: // , - CLUNET_SEND_0; // + case CLUNET_SENDING_STATE_STOP: // Завершение передачи, но надо ещё подождать + CLUNET_SEND_0; // Отпускаем линию CLUNET_TIMER_REG_OCR = now + CLUNET_T; clunetSendingState = CLUNET_SENDING_STATE_DONE; return; - case CLUNET_SENDING_STATE_DONE: // - CLUNET_DISABLE_TIMER_COMP; // - - clunetSendingState = CLUNET_SENDING_STATE_IDLE; // , + case CLUNET_SENDING_STATE_DONE: // Завершение передачи + CLUNET_DISABLE_TIMER_COMP; // Выключаем таймер-сравнение + clunetSendingState = CLUNET_SENDING_STATE_IDLE; // Ставим флаг, что передатчик свободен return; } - if (/*!((clunetReadingState == CLUNET_READING_STATE_DATA) && // [ - (clunetCurrentPrio > clunetReceivingPrio) // - && (clunetSendingState == CLUNET_SENDING_STATE_INIT)) // ] - &&*/ (!CLUNET_SENDING && CLUNET_READING)) // . , + if (/*!((clunetReadingState == CLUNET_READING_STATE_DATA) && // Если мы сейчас не [получаем данные + (clunetCurrentPrio > clunetReceivingPrio) // И приоритет получаемых данных не ниже + && (clunetSendingState == CLUNET_SENDING_STATE_INIT)) // И мы не пытаемся начать инициализацию] + &&*/ (!CLUNET_SENDING && CLUNET_READING)) // То идёт проверка на конфликт. Если мы линию не держим, но она уже занята { - CLUNET_DISABLE_TIMER_COMP; // - - clunetSendingState = CLUNET_SENDING_STATE_WAITING_LINE; // - return; // + CLUNET_DISABLE_TIMER_COMP; // Выключаем таймер-сравнение + clunetSendingState = CLUNET_SENDING_STATE_WAITING_LINE; // Переходим в режим ожидания линии + return; // И умолкаем } - CLUNET_SEND_INVERT; // , + CLUNET_SEND_INVERT; // Сразу инвртируем значение сигнала, у нас это запланировано - if (!CLUNET_SENDING) // ... + if (!CLUNET_SENDING) // Если мы отпустили линию... { - CLUNET_TIMER_REG_OCR = now + CLUNET_T; // CLUNET_T + CLUNET_TIMER_REG_OCR = now + CLUNET_T; // То вернёмся в это прерывание через CLUNET_T единиц времени return; } switch (clunetSendingState) { - case CLUNET_SENDING_STATE_INIT: // + case CLUNET_SENDING_STATE_INIT: // Инициализация CLUNET_TIMER_REG_OCR = now + CLUNET_INIT_T; - clunetSendingState = CLUNET_SENDING_STATE_PRIO1; // + clunetSendingState = CLUNET_SENDING_STATE_PRIO1; // Начинаем следующую фазу return; - case CLUNET_SENDING_STATE_PRIO1: // , - if ((clunetCurrentPrio-1) & 2) // 1, 3T, 0, 1T + case CLUNET_SENDING_STATE_PRIO1: // Фаза передачи приоритета, старший бит + if ((clunetCurrentPrio-1) & 2) // Если 1, то ждём 3T, а если 0, то 1T CLUNET_TIMER_REG_OCR = now + CLUNET_1_T; else CLUNET_TIMER_REG_OCR = now + CLUNET_0_T; clunetSendingState = CLUNET_SENDING_STATE_PRIO2; return; - case CLUNET_SENDING_STATE_PRIO2: // , - if ((clunetCurrentPrio-1) & 1) // 1, 3T, 0, 1T + case CLUNET_SENDING_STATE_PRIO2: // Фаза передачи приоритета, младший бит + if ((clunetCurrentPrio-1) & 1) // Если 1, то ждём 3T, а если 0, то 1T CLUNET_TIMER_REG_OCR = now + CLUNET_1_T; else CLUNET_TIMER_REG_OCR = now + CLUNET_0_T; clunetSendingState = CLUNET_SENDING_STATE_DATA; return; - case CLUNET_SENDING_STATE_DATA: // - if (dataToSend[clunetSendingCurrentByte] & (1 << clunetSendingCurrentBit)) // 1, 3T, 0, 1T + case CLUNET_SENDING_STATE_DATA: // Фаза передачи данных + if (dataToSend[clunetSendingCurrentByte] & (1 << clunetSendingCurrentBit)) // Если 1, то ждём 3T, а если 0, то 1T CLUNET_TIMER_REG_OCR = now + CLUNET_1_T; else CLUNET_TIMER_REG_OCR = now + CLUNET_0_T; - clunetSendingCurrentBit++; // + clunetSendingCurrentBit++; // Переходим к следующему биту if (clunetSendingCurrentBit >= 8) { clunetSendingCurrentBit = 0; clunetSendingCurrentByte++; } - if (clunetSendingCurrentByte >= clunetSendingDataLength) // + if (clunetSendingCurrentByte >= clunetSendingDataLength) // Данные закончились { - clunetSendingState = CLUNET_SENDING_STATE_STOP; // + clunetSendingState = CLUNET_SENDING_STATE_STOP; // Следующая фаза } return; } @@ -131,18 +131,18 @@ ISR(CLUNET_TIMER_COMP_VECTOR) void clunet_start_send() { CLUNET_SEND_0; - if (clunetSendingState != CLUNET_SENDING_STATE_PREINIT) // ... - clunetSendingState = CLUNET_SENDING_STATE_INIT; // - clunetSendingCurrentByte = clunetSendingCurrentBit = 0; // - CLUNET_TIMER_REG_OCR = CLUNET_TIMER_REG+CLUNET_T; // , - - CLUNET_ENABLE_TIMER_COMP; // - + if (clunetSendingState != CLUNET_SENDING_STATE_PREINIT) // Если не нужна пауза... + clunetSendingState = CLUNET_SENDING_STATE_INIT; // Инициализация передачи + clunetSendingCurrentByte = clunetSendingCurrentBit = 0; // Обнуляем счётчик + CLUNET_TIMER_REG_OCR = CLUNET_TIMER_REG+CLUNET_T; // Планируем таймер, обычно почему-то прерывание срабатывает сразу + CLUNET_ENABLE_TIMER_COMP; // Включаем прерывание таймера-сравнения } void clunet_send(unsigned char address, unsigned char prio, unsigned char command, char* data, unsigned char size) { - if (CLUNET_OFFSET_DATA+size+1 > CLUNET_SEND_BUFFER_SIZE) return; // - CLUNET_DISABLE_TIMER_COMP;CLUNET_SEND_0; // , - // + if (CLUNET_OFFSET_DATA+size+1 > CLUNET_SEND_BUFFER_SIZE) return; // Не хватает буфера + CLUNET_DISABLE_TIMER_COMP;CLUNET_SEND_0; // Прерываем текущую передачу, если есть такая + // Заполняем переменные if (clunetSendingState != CLUNET_SENDING_STATE_PREINIT) clunetSendingState = CLUNET_SENDING_STATE_IDLE; clunetCurrentPrio = prio; @@ -156,11 +156,11 @@ void clunet_send(unsigned char address, unsigned char prio, unsigned char comman dataToSend[CLUNET_OFFSET_DATA+size] = check_crc((char*)dataToSend, CLUNET_OFFSET_DATA+size); clunetSendingDataLength = CLUNET_OFFSET_DATA + size + 1; if ( - (clunetReadingState == CLUNET_READING_STATE_IDLE) // , -// || ((clunetReadingState == CLUNET_READING_STATE_DATA) && (prio > clunetReceivingPrio)) // , + (clunetReadingState == CLUNET_READING_STATE_IDLE) // Если мы ничего не получаем в данный момент, то посылаем сразу +// || ((clunetReadingState == CLUNET_READING_STATE_DATA) && (prio > clunetReceivingPrio)) // Либо если получаем, но с более низким приоритетом ) - clunet_start_send(); // - else clunetSendingState = CLUNET_SENDING_STATE_WAITING_LINE; // + clunet_start_send(); // Запускаем передачу сразу + else clunetSendingState = CLUNET_SENDING_STATE_WAITING_LINE; // Иначе ждём линию } inline void clunet_data_received(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size) @@ -168,12 +168,12 @@ inline void clunet_data_received(unsigned char src_address, unsigned char dst_ad if (on_data_received_sniff) (*on_data_received_sniff)(src_address, dst_address, command, data, size); - if (src_address == CLUNET_DEVICE_ID) return; // ! + if (src_address == CLUNET_DEVICE_ID) return; // Игнорируем сообщения от самого себя! if ((dst_address != CLUNET_DEVICE_ID) && - (dst_address != CLUNET_BROADCAST_ADDRESS)) return; // + (dst_address != CLUNET_BROADCAST_ADDRESS)) return; // Игнорируем сообщения не для нас - if (command == CLUNET_COMMAND_REBOOT) // . , + if (command == CLUNET_COMMAND_REBOOT) // Просто ребут. И да, ребутнуть себя мы можем { cli(); set_bit(WDTCR, WDE); @@ -182,14 +182,19 @@ inline void clunet_data_received(unsigned char src_address, unsigned char dst_ad if ((clunetSendingState == CLUNET_SENDING_STATE_IDLE) || (clunetCurrentPrio <= CLUNET_PRIORITY_MESSAGE)) { - if (command == CLUNET_COMMAND_DISCOVERY) // + if (command == CLUNET_COMMAND_DISCOVERY) // Ответ на поиск устройств { +#ifdef CLUNET_DEVICE_NAME char buf[] = CLUNET_DEVICE_NAME; int len = 0; while(buf[len]) len++; clunetSendingState = CLUNET_SENDING_STATE_PREINIT; clunet_send(src_address, CLUNET_PRIORITY_MESSAGE, CLUNET_COMMAND_DISCOVERY_RESPONSE, buf, len); +#else + clunetSendingState = CLUNET_SENDING_STATE_PREINIT; + clunet_send(src_address, CLUNET_PRIORITY_MESSAGE, CLUNET_COMMAND_DISCOVERY_RESPONSE, 0, 0); +#endif } - else if (command == CLUNET_COMMAND_PING) // + else if (command == CLUNET_COMMAND_PING) // Ответ на пинг { clunetSendingState = CLUNET_SENDING_STATE_PREINIT; clunet_send(src_address, CLUNET_PRIORITY_COMMAND, CLUNET_COMMAND_PING_REPLY, data, size); @@ -199,7 +204,7 @@ inline void clunet_data_received(unsigned char src_address, unsigned char dst_ad if (on_data_received) (*on_data_received)(src_address, dst_address, command, data, size); - if ((clunetSendingState == CLUNET_SENDING_STATE_WAITING_LINE) && !CLUNET_READING) // , , + if ((clunetSendingState == CLUNET_SENDING_STATE_WAITING_LINE) && !CLUNET_READING) // Если есть неотосланные данные, шлём, линия освободилась { clunetSendingState = CLUNET_SENDING_STATE_PREINIT; clunet_start_send(); @@ -210,13 +215,13 @@ ISR(CLUNET_TIMER_OVF_VECTOR) { if (clunetTimerPeriods < 3) clunetTimerPeriods++; - else // , + else // Слишком долго нет сигнала, сброс и отключение прерывания { - CLUNET_SEND_0; // ? ... + CLUNET_SEND_0; // А вдруг мы забыли линию отжать? Хотя по идее не должно... clunetReadingState = CLUNET_READING_STATE_IDLE; if ((clunetSendingState == CLUNET_SENDING_STATE_IDLE) && (!CLUNET_READING)) CLUNET_DISABLE_TIMER_OVF; - if ((clunetSendingState == CLUNET_SENDING_STATE_WAITING_LINE) && (!CLUNET_READING)) // , , + if ((clunetSendingState == CLUNET_SENDING_STATE_WAITING_LINE) && (!CLUNET_READING)) // Если есть неотосланные данные, шлём, линия освободилась clunet_start_send(); } } @@ -225,40 +230,44 @@ ISR(CLUNET_TIMER_OVF_VECTOR) ISR(CLUNET_INT_VECTOR) { unsigned char time = (unsigned char)((CLUNET_TIMER_REG-clunetTimerStart) & 0xFF); - if (!CLUNET_READING) // + if (!CLUNET_READING) // Линию отпустило { CLUNET_ENABLE_TIMER_OVF; - if (time >= (CLUNET_INIT_T+CLUNET_1_T)/2) // - , + if (time >= (CLUNET_INIT_T+CLUNET_1_T)/2) // Если кто-то долго жмёт линию, это инициализация { clunetReadingState = CLUNET_READING_STATE_PRIO1; } - else switch (clunetReadingState) // , + else switch (clunetReadingState) // А если не долго, то смотрим на этап { - case CLUNET_READING_STATE_PRIO1: // , + case CLUNET_READING_STATE_PRIO1: // Получение приоритета, клиенту он не нужен + /* if (time > (CLUNET_0_T+CLUNET_1_T)/2) clunetReceivingPrio = 3; else clunetReceivingPrio = 1; + */ clunetReadingState = CLUNET_READING_STATE_PRIO2; break; - case CLUNET_READING_STATE_PRIO2: // , + case CLUNET_READING_STATE_PRIO2: // Получение приоритета, клиенту он не нужен + /* if (time > (CLUNET_0_T+CLUNET_1_T)/2) clunetReceivingPrio++; + */ clunetReadingState = CLUNET_READING_STATE_DATA; clunetReadingCurrentByte = 0; clunetReadingCurrentBit = 0; dataToRead[0] = 0; break; - case CLUNET_READING_STATE_DATA: // + case CLUNET_READING_STATE_DATA: // Чтение всех данных if (time > (CLUNET_0_T+CLUNET_1_T)/2) dataToRead[clunetReadingCurrentByte] |= (1 << clunetReadingCurrentBit); clunetReadingCurrentBit++; - if (clunetReadingCurrentBit >= 8) // + if (clunetReadingCurrentBit >= 8) // Переходим к следующему байту { clunetReadingCurrentByte++; clunetReadingCurrentBit = 0; if (clunetReadingCurrentByte < CLUNET_READ_BUFFER_SIZE) dataToRead[clunetReadingCurrentByte] = 0; - else // + else // Если буфер закончился { clunetReadingState = CLUNET_READING_STATE_IDLE; return; @@ -266,9 +275,9 @@ ISR(CLUNET_INT_VECTOR) } if ((clunetReadingCurrentByte > CLUNET_OFFSET_SIZE) && (clunetReadingCurrentByte > dataToRead[CLUNET_OFFSET_SIZE]+CLUNET_OFFSET_DATA)) { - // , ! + // Получили данные полностью, ура! clunetReadingState = CLUNET_READING_STATE_IDLE; - char crc = check_crc((char*)dataToRead,clunetReadingCurrentByte); // CRC + char crc = check_crc((char*)dataToRead,clunetReadingCurrentByte); // Проверяем CRC if (crc == 0) clunet_data_received(dataToRead[CLUNET_OFFSET_SRC_ADDRESS], dataToRead[CLUNET_OFFSET_DST_ADDRESS], dataToRead[CLUNET_OFFSET_COMMAND], (char*)(dataToRead+CLUNET_OFFSET_DATA), dataToRead[CLUNET_OFFSET_SIZE]); } @@ -290,13 +299,16 @@ void clunet_init() CLUNET_READ_INIT; CLUNET_TIMER_INIT; CLUNET_INIT_INT; +#ifdef CLUNET_ENABLE_INT CLUNET_ENABLE_INT; +#warning CLUNET_ENABLE_INT is deprecated +#endif char reset_source = MCUCSR; clunet_send(CLUNET_BROADCAST_ADDRESS, CLUNET_PRIORITY_MESSAGE, CLUNET_COMMAND_BOOT_COMPLETED, &reset_source, 1); MCUCSR = 0; } -int clunet_ready_to_send() // 0, , +int clunet_ready_to_send() // Возвращает 0, если готов к передаче, иначе приоритет текущей задачи { if (clunetSendingState == CLUNET_SENDING_STATE_IDLE) return 0; return clunetCurrentPrio; diff --git a/clunet.h b/clunet.h index f19145c..5869611 100644 --- a/clunet.h +++ b/clunet.h @@ -1,7 +1,7 @@ /* Name: clunet.h * Project: CLUNET network driver * Author: Alexey Avdyukhin - * Creation Date: 2013-07-23 + * Creation Date: 2013-09-09 * License: DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE */ @@ -36,124 +36,126 @@ #define CLUNET_BROADCAST_ADDRESS 0xFF #define CLUNET_COMMAND_DISCOVERY 0x00 -/* , */ +/* Поиск других устройств, параметров нет */ #define CLUNET_COMMAND_DISCOVERY_RESPONSE 0x01 -/* , - () */ +/* Ответ устройств на поиск, в качестве параметра - название устройства (текст) */ #define CLUNET_COMMAND_BOOT_CONTROL 0x02 -/* . - . -<-0 - -->1 - -<-2 - , - -->3 , 4 - , - ( ) -<-4 -->5 */ +/* Работа с загрузчиком. Данные - субкоманда. +<-0 - загрузчик запущен +->1 - перейти в режим обновления прошивки +<-2 - подтверждение перехода, плюс два байта - размер страницы +->3 запись прошивки, 4 байта - адрес, всё остальное - данные (равные размеру страницы) +<-4 блок прошивки записан +->5 выход из режима прошивки */ #define CLUNET_COMMAND_REBOOT 0x03 -/* . */ +/* Перезагружает устройство в загрузчик. */ #define CLUNET_COMMAND_BOOT_COMPLETED 0x04 -/* , . - MCU , . */ +/* Посылается устройством после инициализации библиотеки, сообщает об успешной загрузке устройства. Параметр - содержимое MCU регистра, говорящее о причине перезагрузки. */ #define CLUNET_COMMAND_DOOR_INFO 0x05 -/* . -0 - -1 - -2 - */ +/*Информация об открытии двери. +0 - закрыта +1 - открыта +2 - тревога */ #define CLUNET_COMMAND_DEVICE_POWER_INFO_REQUEST 0x06 -/* */ +/* Запрашивает информацию о состоянии выключателей */ #define CLUNET_COMMAND_DEVICE_POWER_INFO 0x07 -/* . - . */ +/* Состояние выключателей. Параметр - битовая маска состояния выключателей. */ #define CLUNET_COMMAND_DEVICE_POWER_COMMAND 0x08 -/* / . - . 0xFE - , 0xFF - . */ +/* Включает/выключает выключатели. Параметр - битовая маска. Для света 0xFE - убавить свет, а 0xFF - прибавить. */ #define CLUNET_COMMAND_SET_TIMER 0x09 -/* . - - ( ) */ +/* Установка таймера. Параметр - кол-во секунд (два байта) */ #define CLUNET_COMMAND_RC_BUTTON_PRESSED 0x0A -/* . - , - . - 01 - (Sony ?) - 4 . -02 - . */ +/* Нажата кнопка на пульте. Первый байт - тип кода, далее - номер кнопки. +На данный момент 01 - самый популярный стандарт (Sony вроде?) длина кода кнопки - 4 байта. +02 - удержание кнопки его же. */ #define CLUNET_COMMAND_RC_BUTTON_PRESSED_RAW 0x0B -/* . 4 . 2 - 2 - 0.032 . (1/8000000*256 ) */ +/* Недекодированные данные о нажатой кнопке на пульте для нестандартных пультов. Идут пачками по 4 байта. 2 из которых - длительность сигнала и 2 - длительность его отсутствия в 0.032 долях миллисекунды. (1/8000000*256 сек) */ #define CLUNET_COMMAND_RC_BUTTON_SEND 0x0C -/* . CLUNET_COMMAND_RC_BUTTON_PRESSED, (- ), Sony ~30 */ +/* Заэмулировать кнопку пульта. Формат данных аналогичен CLUNET_COMMAND_RC_BUTTON_PRESSED, плюс в конце опциональный байт длительности удержания кнопки (кол-во дополнительных сигналов), для Sony это ~30мс */ #define CLUNET_COMMAND_RC_BUTTON_SEND_RAW 0x0D -/* . CLUNET_COMMAND_RC_BUTTON_PRESSED_RAW. */ +/* Заэмулировать кнопку пульта на основе сырых данных. Формат данных аналогичен CLUNET_COMMAND_RC_BUTTON_PRESSED_RAW. */ #define CLUNET_COMMAND_LIGHT_LEVEL 0x0E -/* . - 2 (0x0000 - 0x1FFF, 0x1FFF - 0 , 0x0000 - 5 ). */ +/* Сообщает об уровне освещения. Параметр - 2 байта (0x0000 - 0x1FFF, где 0x1FFF - 0 вольт между фотодиодом и землёй, а 0x0000 - 5 вольт). */ #define CLUNET_COMMAND_ONEWIRE_START_SEARCH 0x0F -/* 1-wire , . */ +/* Запуск поиска 1-wire устройств, данные пустые. */ #define CLUNET_COMMAND_ONEWIRE_DEVICE_FOUND 0x10 -/* 1-wire . - 8 , , CRC. */ +/* Сообщает о найденном 1-wire устройсте. Данные - 8 байт, включающие тип устройства, серийный номер и CRC. */ #define CLUNET_COMMAND_TEMPERATURE 0x11 -/* . 1 - , 6 - , 2 - ( , !) */ +/* Сообщает о температуре. 1 байт - тип устройства, 6 - серийник, 2 - температура в формате устройства (смотреть на тип, чтобы декодировать!) */ #define CLUNET_COMMAND_TIME 0x12 -/* . - , , , ( 1900), ( 0), ( 1) */ +/* Сообщает время. Шесть байт - часы, минуты, секунды, год (от 1900), месяц (от 0), день (от 1) */ #define CLUNET_COMMAND_WHEEL 0x13 -/* , - ID , - */ +/* Сообщает обороты колеса мыши, первый байт - ID колеса, далее два байта - обороты */ #define CLUNET_COMMAND_VOLTAGE 0x14 -/* , - ID , - , 0x3FF = 5.12 */ +/* Сообщает напряжение на батарейке, первый байт - ID устройства, далее два байта - вольтаж, где 0x3FF = 5.12 */ #define CLUNET_COMMAND_MOTION 0x15 -/* , , - ID / */ +/* Сообщает, что в помещении есть движение, первый байт - ID датчика/камеры */ #define CLUNET_COMMAND_INTERCOM_RING 0x16 -/* */ +/* Звонок в домофон */ #define CLUNET_COMMAND_INTERCOM_MESSAGE 0x17 -/* , 4 - */ +/* Новое сообщение на автоответчике домофона, в данных 4 байта - номер сообщения */ #define CLUNET_COMMAND_INTERCOM_MODE_REQUEST 0x18 -/* */ +/* Запрашивает режим работы домофона */ #define CLUNET_COMMAND_INTERCOM_MODE_INFO 0x19 -/* , - , - */ +/* Сообщает режим работы домофона, первый байт - постоянный режим, второй - временный */ #define CLUNET_COMMAND_INTERCOM_MODE_SET 0x1A -/* , - ( 0xFF, ), - () */ +/* Задаёт режим работы домофона, первый байт - постоянный режим (или 0xFF, чтобы не трогать), второй - временный (опционально) */ #define CLUNET_COMMAND_INTERCOM_RECORD_REQUEST 0x1B -/* , - 4 , - 1 , 1 , 0 - */ +/* Запрашивает запись у домофона, подтверждает доставку или завершает передачу + Если 4 байта, то это номер запрашиваемой записи + Если 1 байт, то 1 в случае подтверждения получения пакета, 0 - завершение передачи */ #define CLUNET_COMMAND_INTERCOM_RECORD_DATA 0x1C -/* . 4 - , 4 - , - */ +/* Передаёт кусок записи с автоответчика. Первые 4 байта - номер записи, далее 4 байта - смещение от начала файла, всё далее - данные из файла */ #define CLUNET_COMMAND_PING 0xFE -/* , , */ +/* Пинг, на эту команду устройство должно ответить следующей командой, возвратив весь буфер */ #define CLUNET_COMMAND_PING_REPLY 0xFF -/* , , */ +/* Ответ на пинг, в данных то, что было прислано в предыдущей команде */ #define CLUNET_PRIORITY_NOTICE 1 -/* 1 - , */ +/* Приоритет пакета 1 - неважное уведомление, которое вообще может быть потеряно без последствий */ #define CLUNET_PRIORITY_INFO 2 -/* 2 - - , */ +/* Приоритет пакета 2 - какая-то информация, не очень важная */ #define CLUNET_PRIORITY_MESSAGE 3 -/* 3 - - */ +/* Приоритет пакета 3 - сообщение с какой-то важной информацией */ #define CLUNET_PRIORITY_COMMAND 4 -/* 4 - , */ +/* Приоритет пакета 4 - команда, на которую нужно сразу отреагировать */ +#ifndef CLUNET_T #define CLUNET_T ((F_CPU / CLUNET_TIMER_PRESCALER) / 15625) +#endif #if CLUNET_T < 8 # error Timer frequency is too small, increase CPU frequency or decrease timer prescaler #endif @@ -200,20 +202,20 @@ # error CLUNET_READ_BUFFER_SIZE must be <= 255 #endif -// +// Инициализация void clunet_init(); -// +// Отправка пакета void clunet_send(unsigned char address, unsigned char prio, unsigned char command, char* data, unsigned char size); -// 0, , +// Возвращает 0, если готов к передаче, иначе приоритет текущей задачи int clunet_ready_to_send(); -// , -// - , +// Установка функций, которые вызываются при получении пакетов +// Эта - получает пакеты, которые адресованы нам void clunet_set_on_data_received(void (*f)(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size)); -// - , , +// А эта - абсолютно все, которые ходят по сети, включая наши void clunet_set_on_data_received_sniff(void (*f)(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size)); char check_crc(char* data, unsigned char size); diff --git a/clunet_config.h b/clunet_config.h index 7369e95..925fb28 100644 --- a/clunet_config.h +++ b/clunet_config.h @@ -47,8 +47,7 @@ #define CLUNET_DISABLE_TIMER_OVF unset_bit(TIMSK, TOIE2) // -#define CLUNET_INIT_INT {set_bit(EICRA,ISC10);unset_bit(EICRA,ISC11);} -#define CLUNET_ENABLE_INT set_bit(EIMSK, INT1) +#define CLUNET_INIT_INT {set_bit(EICRA,ISC10);unset_bit(EICRA,ISC11);set_bit(EIMSK, INT1);} // #define CLUNET_TIMER_COMP_VECTOR TIMER2_COMP_vect diff --git a/intercom.c b/intercom.c index 9204e26..2851841 100644 --- a/intercom.c +++ b/intercom.c @@ -13,8 +13,8 @@ #include "transfer.h" -volatile unsigned char mode_current = 1; // -volatile unsigned char mode_temp = 0; // +volatile unsigned char mode_current = 1; // Текущий режим +volatile unsigned char mode_temp = 0; // Режим на один раз volatile unsigned long int record_num = 0; char buffer[32]; @@ -43,41 +43,41 @@ void send_current_mode(unsigned char dest) { buffer[0] = mode_current; buffer[1] = mode_temp; - clunet_send(dest, CLUNET_PRIORITY_INFO, CLUNET_COMMAND_INTERCOM_MODE_INFO, (char*)&buffer, 2); // + clunet_send(dest, CLUNET_PRIORITY_INFO, CLUNET_COMMAND_INTERCOM_MODE_INFO, (char*)&buffer, 2); // Отправляем в сеть текущий режим } void save_mode() { - eeprom_write_byte((void*)4, mode_current); // - eeprom_write_byte((void*)5, mode_temp); // + eeprom_write_byte((void*)4, mode_current); // Режим + eeprom_write_byte((void*)5, mode_temp); // Временный режим send_current_mode(CLUNET_BROADCAST_ADDRESS); } void data_received(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size) { - if (command == CLUNET_COMMAND_TIME && size >= 6) // + if (command == CLUNET_COMMAND_TIME && size >= 6) // Синхронизация времени { set_time(data[3]+2000, data[4], data[5], data[0],data[1],data[2]); } - else if (command == CLUNET_COMMAND_INTERCOM_MODE_REQUEST) // + else if (command == CLUNET_COMMAND_INTERCOM_MODE_REQUEST) // У нас запрашивают режим { send_current_mode(src_address); } - else if (command == CLUNET_COMMAND_INTERCOM_MODE_SET) // + else if (command == CLUNET_COMMAND_INTERCOM_MODE_SET) // Установка режима { if (size >= 1 && (unsigned char)data[0] != 0xFF) mode_current = data[0]; if (size >= 2 && (unsigned char)data[1] != 0xFF) mode_temp = data[1]; save_mode(); } - else if (command == CLUNET_COMMAND_INTERCOM_RECORD_REQUEST) // + else if (command == CLUNET_COMMAND_INTERCOM_RECORD_REQUEST) // Передача записей { - if (size == 4) transfer_start(*((unsigned long int*)data), src_address); // - else if (size == 1 && data[0] == 1) transfer_ack(); // , - else if (size == 1 && data[0] == 0) transfer_stop(); // + if (size == 4) transfer_start(*((unsigned long int*)data), src_address); // Начинаем передачу + else if (size == 1 && data[0] == 1) transfer_ack(); // Подтвержают приём, переходим к следующему куску + else if (size == 1 && data[0] == 0) transfer_stop(); // Прекращение передачи данных } } -int is_LINE_POWER() // , +int is_LINE_POWER() // Определяет, что есть стабильный сигнал в линии { int i; for (i = 0; i < 10; i++) @@ -88,7 +88,7 @@ int is_LINE_POWER() // return 1; } -void intercom_bell() // +void intercom_bell() // Издаёт звук входящего звонка { int t; for (t = 0; t < 9; t++) @@ -101,7 +101,7 @@ void intercom_bell() // } } -int answer_play(char* filename) // +int answer_play(char* filename) // Отвечает и воспроизводит файл { ANSWER; MODE_MYSOUND; @@ -110,7 +110,7 @@ int answer_play(char* filename) // { while (sound_read() >= 0) { - if (!LINE_POWER || OFFHOOK) // , + if (!LINE_POWER || OFFHOOK) // Сняли трубку, или сигнал исчез { sound_stop(); return 1; @@ -121,23 +121,23 @@ int answer_play(char* filename) // return 0; } -int answer_play_open(char* filename) // , +int answer_play_open(char* filename) // Отвечает, воспроизводит файл и открывает дверь { - if (answer_play(filename)) return 1; // , + if (answer_play(filename)) return 1; // Сняли трубку, или сигнал исчез OPEN; return 0; } -int answer_record(char* filename1, char* filename2) // , , +int answer_record(char* filename1, char* filename2) // Отвечает, записывает сообщение, { - if (answer_play(filename1)) return 1; // , - beep(3000, 500); // - sprintf(buffer, "/%08lu.wav", record_num); // - clunet_send(CLUNET_BROADCAST_ADDRESS, CLUNET_PRIORITY_INFO, CLUNET_COMMAND_INTERCOM_MESSAGE, (char*)&record_num, sizeof(record_num)); // + if (answer_play(filename1)) return 1; // Отвечаем, предлагаем оставить сообщение + beep(3000, 500); // Биип + sprintf(buffer, "/%08lu.wav", record_num); // Формируем имя файла + clunet_send(CLUNET_BROADCAST_ADDRESS, CLUNET_PRIORITY_INFO, CLUNET_COMMAND_INTERCOM_MESSAGE, (char*)&record_num, sizeof(record_num)); // Отправляем в сеть сообщение record_num++; - eeprom_write_dword((void*)0, record_num); // - - if (rec_wav(buffer) == 0) // + eeprom_write_dword((void*)0, record_num); // Запоминаем кол-во записей + if (rec_wav(buffer) == 0) // Пишем сообщение { int s = 0; long int totalSize = 0; @@ -145,7 +145,7 @@ int answer_record(char* filename1, char* filename2) // { s = sound_write(); totalSize += s; - if (!LINE_POWER || OFFHOOK) // , + if (!LINE_POWER || OFFHOOK) // Сняли трубку, или сигнал исчез { sound_stop(); return 1; @@ -153,11 +153,11 @@ int answer_record(char* filename1, char* filename2) // } sound_stop(); } - if (play_wav_pgm(filename2) == 0) // , + if (play_wav_pgm(filename2) == 0) // Если пациент дождался, благодарим { while (sound_read() >= 0) { - if (!LINE_POWER || OFFHOOK) // , + if (!LINE_POWER || OFFHOOK) // Сняли трубку, или сигнал исчез { sound_stop(); return 1; @@ -168,19 +168,19 @@ int answer_record(char* filename1, char* filename2) // return 0; } -void incoming_ring() // +void incoming_ring() // Выполняется при любом входящем звонке { LED_RED_ON; - unsigned char mode = (mode_temp != 0) ? mode_temp : mode_current; // - // , + unsigned char mode = (mode_temp != 0) ? mode_temp : mode_current; // Текущий режим + // Сообщение о звонке, указываем текущий режим clunet_send(CLUNET_BROADCAST_ADDRESS, CLUNET_PRIORITY_INFO, CLUNET_COMMAND_INTERCOM_RING, (char*)&mode, 1); intercom_bell(); - if (mode_temp) // + if (mode_temp) // Обнуляем временный режим { mode_temp = 0; save_mode(); } - if (!LINE_POWER) // , + if (!LINE_POWER) // Аварийное откртие двери, если набрали и сразу сбросили { mode_temp = 0xFF; save_mode(); @@ -189,38 +189,38 @@ void incoming_ring() // { switch (mode) { - case 1: // , , + case 1: // Автоответчик, долго ждёт ответа, потом записывает answer_record(AUTOLONG_WAV, SAVED_WAV); break; - case 2: // , + case 2: // Автоответчик, сразу записывает answer_record(AUTOFAST_WAV, SAVED_WAV); break; - case 3: // , + case 3: // Приветствует хозяина, открывает дверь answer_play_open(OPENME_WAV); break; - case 4: // , + case 4: // Приветствует гостя, открывает дверь answer_play_open(OPEN_WAV); break; - case 5: // . . + case 5: // Долго ждёт ответа. Сообщение не пишет. answer_play(WAITLONG_WAV); break; - case 9: // , . , , . + case 9: // Здрасти, здрастите. Проходи, братишка, проходи. answer_play_open(MODE9_WAV); break; - case 0xFF: // + case 0xFF: // Аварийное откртие двери answer_play_open(EMERGENCY_OPEN_WAV); } MODE_NORMAL; - _delay_ms(200); // , + _delay_ms(200); // На случай, если контакты снятия трубки не успели разомкнуться HANGUP; } - while (LINE_POWER); // + while (LINE_POWER); // Ждём пока не пропадёт сигнал LED_RED_OFF; - while (OFFHOOK); // - _delay_ms(100); // + while (OFFHOOK); // И пользователь не положит трубку + _delay_ms(100); // Защита от дребезга контактов } -int count_disk() // , +int count_disk() // Считает, что набрали на диске { int cnt = 1; while (1) @@ -280,7 +280,7 @@ void say_mode(char istemp) } } -void select_mode(char istemp) // +void select_mode(char istemp) // Выбот режима { say_mode(istemp); while (!CONTROL && OFFHOOK) play_wav_auto_pgm(MODELIST_WAV); @@ -300,11 +300,11 @@ void select_mode(char istemp) // void play_record(long unsigned int num) { - sprintf(buffer, "/%08lu.wav", num); // + sprintf(buffer, "/%08lu.wav", num); // Формируем имя файла play_wav_auto(buffer); } -void control_mode() // +void control_mode() // Режим управления { LED_GREEN_ON; while (OFFHOOK) @@ -332,7 +332,7 @@ void control_mode() // } } LED_GREEN_OFF; - _delay_ms(100); // + _delay_ms(100); // Защита от дребезга контактов } int main (void) @@ -342,19 +342,19 @@ int main (void) time_init(); sei(); //eeprom_write_dword((void*)0, 0); - record_num = eeprom_read_dword((void*)0); // - - mode_current = eeprom_read_byte((void*)4); // - mode_temp = eeprom_read_byte((void*)5); // + record_num = eeprom_read_dword((void*)0); // Читаем кол-во записей + mode_current = eeprom_read_byte((void*)4); // Режим + mode_temp = eeprom_read_byte((void*)5); // Временный режим disk_initialize(0); - unset_bit(DDRA, 3); set_bit(PORTA, 3); // - unset_bit(DDRA, 4); unset_bit(PORTA, 4); // - set_bit(DDRA, 5); HANGUP; // - set_bit(DDRA, 6); MODE_NORMAL; // - unset_bit(DDRG, 0); set_bit(PORTG, 0); // , - set_bit(DDRD, 6); set_bit(DDRD, 7); // - unset_bit(DDRA, 7); set_bit(PORTA, 7); // + unset_bit(DDRA, 3); set_bit(PORTA, 3); // Определение сигнала в линии + unset_bit(DDRA, 4); unset_bit(PORTA, 4); // Открывалка двери + set_bit(DDRA, 5); HANGUP; // Реле снимания трубки + set_bit(DDRA, 6); MODE_NORMAL; // Реле выбора режима + unset_bit(DDRG, 0); set_bit(PORTG, 0); // Определение, лежит ли трубка + set_bit(DDRD, 6); set_bit(DDRD, 7); // Светодиоды + unset_bit(DDRA, 7); set_bit(PORTA, 7); // Счётчик оборотов диска unset_bit(DDRF, 0); // ADC+ unset_bit(PORTF, 0); @@ -385,7 +385,7 @@ int main (void) { if (is_LINE_POWER()) incoming_ring(); if (OFFHOOK) control_mode(); - transfer_data(); // . + transfer_data(); // Передаём данные на досуге. //play_wav_auto("/00000007.wav"); } } -- cgit v1.2.3