From ced434cba51302bb36bfecb16da5909f8e5d2d03 Mon Sep 17 00:00:00 2001 From: Alexey 'Cluster' Avdyukhin Date: Wed, 22 Jan 2014 22:06:26 +0400 Subject: Code comments --- defines.h | 1 + ibutton.c | 194 ++++++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 121 insertions(+), 74 deletions(-) diff --git a/defines.h b/defines.h index ad715df..f52d25c 100644 --- a/defines.h +++ b/defines.h @@ -1,6 +1,7 @@ #define F_CPU 8000000UL #define UART_BAUD 19200 +#define DEBUG #define LED_TOP_PORT C #define LED_TOP_PIN 0 diff --git a/ibutton.c b/ibutton.c index b47a079..253bfc7 100644 --- a/ibutton.c +++ b/ibutton.c @@ -13,8 +13,7 @@ #include "metacom.h" #include "usb.h" -#define DEBUG - +// Некоторые универсальные ключи unsigned char VEZDEHOD_KEY1[] PROGMEM = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D}; unsigned char VEZDEHOD_KEY2[] PROGMEM = {0x01, 0xBE, 0x40, 0x11, 0x5A, 0x36, 0x00, 0xE1}; unsigned char VEZDEHOD_KEY3[] PROGMEM = {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F}; @@ -58,17 +57,22 @@ uint8_t debug_log_size = 0; #else #define WRITE_LOG(t) ; #endif + ISR(INT0_vect) { + // Выключаем прерывание после срабатывания + // Его цель - только вывести устройство из спящего режима unset_bit(GICR, INT0); } ISR(INT1_vect) { + // Выключаем прерывание после срабатывания + // Его цель - только вывести устройство из спящего режима unset_bit(GICR, INT1); } - +// Включает заданные светодиоды по маске void set_leds(unsigned char leds_mask) { if (leds_mask & (1<<0)) set_bit(LED1_PORT, LED1_PIN); else unset_bit(LED1_PORT, LED1_PIN); // top led @@ -80,29 +84,33 @@ void set_leds(unsigned char leds_mask) if (leds_mask & (1<<6)) set_bit(LED7_PORT, LED7_PIN); else unset_bit(LED7_PORT, LED7_PIN); // center led } +// Ускоряет мигание светодиодами void speedup_leds(void) { leds_time+=32; } +// Зажигаем следующий светодиод, если надо, +// т.е. в каждый момент времени горит только один void update_leds(void) { leds_time++; - //if (leds_time >= 16) leds_time = 0; if ((leds_mask & (1<<7)) && ((leds_time >> 13) % 2 == 1)) set_leds(0); else set_leds(leds_mask & (1UL << (leds_time % 16))); } +// Зажигаем следующий светодиод, но больше времени уделяем на горение, +// т.е. светодиоды визуально светятся ярче void update_leds_bright(void) { leds_time++; - //if (leds_time > 6) leds_time = 0; if ((leds_mask & (1<<7)) && ((leds_time >> 13) % 2 == 1)) set_leds(0); else set_leds(leds_mask & (1UL << (leds_time % 8))); } +// Отображает заданную цифру void show_digit(unsigned char digit) { unsigned char mask = 0; @@ -131,6 +139,7 @@ void show_digit(unsigned char digit) set_leds(mask); } +// Проверяет, есть ли заданный ключ в базе int key_exists(unsigned char* new_key) { unsigned char i, i2, bingo; @@ -145,19 +154,16 @@ int key_exists(unsigned char* new_key) return 0; } +// Считывает ключ int read_mode() { onewire_init(); -/* - USART_init(); - set_bit(UCSRB, TXEN); // TX - */ int t = 0; unsigned char serial[8]; char read_ok = 0; - leds_mask = 1<<6; + leds_mask = 1<<6; // Во время считывания мигаем средним светодиодом while (BUTTON_PRESSED) { wdt_reset(); @@ -169,23 +175,31 @@ int read_mode() { wdt_reset(); update_leds(); - char res = onewire_write_reset(); - if (res) + char res = onewire_write_reset(); // Посылает 1-wire ресет + if (res) // Если устройство ответило... { + // Посылаем команду считывания ключа onewire_write_byte(ONEWIRE_COMMAND_READ_ROM); int b; + // Читаем 8 байт из ключа for (b = 0; b < 8; b++) serial[b] = onewire_read_byte(); + // Проверяем CRC if ((onewire_check_crc(serial, 8) == 0) && !onewire_all_zeros(serial, 8)) { read_ok = 1; } } - CYFRAL_PULLUP_ENABLE; // 750 - CYFRAL_REFERENCE_ENABLE; // - long int code = read_cyfral_with_check(); + + // Теперь пытаемся прочитать цифрал-клюс + CYFRAL_PULLUP_ENABLE; // подтяжка 750 Ом + CYFRAL_REFERENCE_ENABLE; // делитель напряженния + // Читаем ключ несколько раз, с проверкой + long int code = read_cyfral_with_check(); + // Выключаем назад подтяжку и делитель напряжения CYFRAL_PULLUP_DISABLE; CYFRAL_REFERENCE_DISABLE; + // Если ключ прочитан успешно... if (code >= 0) { serial[0] = 0xFF; @@ -195,24 +209,25 @@ int read_mode() read_ok = 1; } t++; + // После 2000 неудачных попыток выходим и выключаемся if (t > 2000) - { return 0; - } - if (BUTTON_PRESSED || USB_POWERED) - { - return 1; // - } + if (BUTTON_PRESSED || USB_POWERED) // При нажатии кнопки или подключения USB... + return 1; // возврат в основной режим + // Если ключ прочитан успешно... if (read_ok) { read_ok = 0; t = 0; + // Проверяем - нет ли у нас уже такого ключа? int exists = key_exists(serial); int num; + // Если нет... if (!exists) { + // Сохраняем ключ current_key = key_count; key_count++; eeprom_write_block(serial, (void*)(key_count*8), 8); @@ -220,8 +235,10 @@ int read_mode() num = key_count; } else { + // Иначе отображаем номер существующего num = exists; } + // Мигаем три раза номером ключа for (t = 0; t < 3; t++) { show_digit(num); @@ -244,11 +261,12 @@ int read_mode() } } -int ibutton_read_byte_from_master(unsigned char* value) // . - 0, - 1, - 2 +// Читает байт от мастера. Таймаут - возвращает 0, ресет - 1, удачно - 2 +int ibutton_read_byte_from_master(unsigned char* value) { int i; *value = 0; - for (i = 0; i < 8; i++) // + for (i = 0; i < 8; i++) // Ждем команду { TCNT1 = 0; while (!ONEWIRE_MASTER_RX && (TCNT1 < 30000)); if (TCNT1 >= 30000) return 0; TCNT1 = 0; while (ONEWIRE_MASTER_RX && (TCNT1 < 30000)); @@ -258,87 +276,101 @@ int ibutton_read_byte_from_master(unsigned char* value) // return 2; } +// Посылает мастуру presence-pulse и ждёт команду int ibutton_wait_for_master3(unsigned char* key) { wdt_reset(); - set_leds(0); // , .. - ONEWIRE_WAIT(20) // delay 20us - ONEWIRE_MASTER_TX(140); + set_leds(0); // Гасим светодиоды, т.к. нет времени ими мигать + ONEWIRE_WAIT(20) // Немножко ждём + ONEWIRE_MASTER_TX(140); // Presence-pulse + // Ждём возобновления линии TCNT1 = 0; while (ONEWIRE_MASTER_RX && (TCNT1 < 30000)); - if (TCNT1 >= 300) return 1; + if (TCNT1 >= 300) return 1; // Если линия долго прижата мастером, это ресет int i, bit; unsigned char command = 0; - i = ibutton_read_byte_from_master(&command); // + i = ibutton_read_byte_from_master(&command); // Получаем комманду if (i != 2) return i; + WRITE_LOG(command); - if (command == ONEWIRE_COMMAND_SKIP_ROM) // SKIP_ROM . . + if (command == ONEWIRE_COMMAND_SKIP_ROM) // Если нам сначала прислали SKIP_ROM команду. На практике такого не бывало. { i = ibutton_read_byte_from_master(&command); if (i != 2) return i; + WRITE_LOG(command); } - WRITE_LOG(command); - if ((command == ONEWIRE_COMMAND_READ_ROM) || (command == ONEWIRE_COMMAND_READ_ROM_ALT)) // , + if ((command == ONEWIRE_COMMAND_READ_ROM) || (command == ONEWIRE_COMMAND_READ_ROM_ALT)) // Получили запрос, шлём ключ { for (i = 0; i < 8; i++) { for (bit = 0; bit < 8; bit++) { + // Ждём запроса от мастера TCNT1 = 0; while ((!ONEWIRE_MASTER_RX) && (TCNT1 < 30000)); if (TCNT1 >= 30000) return 0; + // Если нужно передать логический ноль, прижимаем линию if (((key[i] >> bit) & 1) == 0) { ONEWIRE_MASTER_TX(35); } + // Ждём возобновления линии TCNT1 = 0; while (ONEWIRE_MASTER_RX && (TCNT1 < 30000)); - if (TCNT1 >= 300) return 1; + if (TCNT1 >= 300) return 1; // Если линия долго прижата мастером, это ресет } } } - if (command == ONEWIRE_COMMAND_SEARCH) // ! + if (command == ONEWIRE_COMMAND_SEARCH) // Мастер выполняет поиск! { for (i = 0; i < 8; i++) { for (bit = 0; bit < 8; bit++) { - char d = (key[i] >> bit) & 1; // + char d = (key[i] >> bit) & 1; // Текущий бит + // Ждём запроса от мастера TCNT1 = 0; while ((!ONEWIRE_MASTER_RX) && (TCNT1 < 30000)); if (TCNT1 >= 30000) return 0; - if (d == 0) // + if (d == 0) // Если нужно передать логический ноль, прижимаем линию { ONEWIRE_MASTER_TX(35); } + // Ждём возобновления линии TCNT1 = 0; while (ONEWIRE_MASTER_RX && (TCNT1 < 30000)); - if (TCNT1 >= 300) return 1; + if (TCNT1 >= 300) return 1; // Если линия долго прижата мастером, это ресет + // Ждём запроса от мастера TCNT1 = 0; while ((!ONEWIRE_MASTER_RX) && (TCNT1 < 30000)); if (TCNT1 >= 30000) return 0; - if (d != 0) + if (d != 0) // Если нужно передать логическую единицу, прижимаем линию { ONEWIRE_MASTER_TX(35); } + // Ждём возобновления линии TCNT1 = 0; while (ONEWIRE_MASTER_RX && (TCNT1 < 30000)); - if (TCNT1 >= 300) return 1; + if (TCNT1 >= 300) return 1; // Если линия долго прижата мастером, это ресет + // Ждём сигнала от мастера TCNT1 = 0; while (!ONEWIRE_MASTER_RX && (TCNT1 < 30000)); if (TCNT1 >= 30000) return 0; + // Ждём возобновления линии TCNT1 = 0; while (ONEWIRE_MASTER_RX && (TCNT1 < 30000)); - if (TCNT1 >= 300) return 1; + if (TCNT1 >= 300) return 1; // Если линия долго прижата мастером, это ресет char d2; - if (TCNT1 < 45) d2 = 1; else d2 = 0; // , - if (d != d2) return 0; // , + if (TCNT1 < 45) d2 = 1; else d2 = 0; // Бит, который подтверждает мастер + if (d != d2) return 0; // Если они не совпадают, выходим } } } return 0; } +// Отвечает на ресет мастеру void ibutton_wait_for_master2(unsigned char* key) { int reset; do { reset = ibutton_wait_for_master3(key); - } while (reset); // , + } while (reset); // Если в результате общения получили ресет, то начинаем общение заново } +// Ждём ресета от мастера void ibutton_wait_for_master(unsigned char* key) { int waittime; @@ -346,33 +378,39 @@ void ibutton_wait_for_master(unsigned char* key) { wdt_reset(); TCNT1 = 0; - while (!ONEWIRE_MASTER_RX && (TCNT1 < 30000)) // + while (!ONEWIRE_MASTER_RX && (TCNT1 < 30000)) // Пока нет сигнала { wdt_reset(); update_leds(); if (BUTTON_PRESSED || USB_POWERED) return; }; + // Если долго не было сигнала, ждём дальше if (TCNT1 >= 30000) continue; + // Если же сигнал есть, считаем время TCNT1 = 0; - while (ONEWIRE_MASTER_RX) if (TCNT1 > 30000) TCNT1 = 30000; // - if (TCNT1 > 300) // + while (ONEWIRE_MASTER_RX) if (TCNT1 > 30000) TCNT1 = 30000; // Пока есть сигнал + if (TCNT1 > 300) // Не слишком короткий { - ibutton_wait_for_master2(key); // , - } + ibutton_wait_for_master2(key); // Дверь заговорила, отвечаем + } + // Был сигнал, ждём ресета с нуля waittime = 0; } - ibutton_wait_for_master2(key); // , + ibutton_wait_for_master2(key); // Не дождались, начинаем сами } - +// Режим посылки ключа int send_mode() { + // Если ключей нет, сразу переходим в режим чтения ключей if (!key_count) return 1; int t; while (1) { if (current_key >= key_count) current_key = 0; + // Показываем номер текущего ключа show_digit(current_key+1); + // Ждём пока кнопку, отпустят while (BUTTON_PRESSED) { wdt_reset(); @@ -380,35 +418,43 @@ int send_mode() _delay_ms(1); } unsigned char key[8]; + // В обычном режиме читаем ключ из EEPROM if (!vezdehod_mode) eeprom_read_block(key, (void*)((current_key+1)*8), 8); else - { // , PGM + { // Если режим вездехода, то читаем ключ из PGM памяти int i; for (i = 0; i < 8; i++) key[i] = pgm_read_byte(&VEZDEHOD_KEYS[current_key][i]); } + // Включаем 1-wire onewire_init(); t = 0; while (1) { - if (key[0] == 0xFF) // + if (key[0] == 0xFF) // Цифрал { + // После 1000 попыток выключаемся if (t > 1000) return 0; wdt_reset(); speedup_leds(); update_leds(); uint16_t cyfral_key = key[1] + key[2]*0x100; + // Посылаем ключ cyfral_send(cyfral_key); } - else if (key[0] == 0xFE) // + else if (key[0] == 0xFE) // Метаком { + // После 1000 попыток выключаемся if (t > 1000) return 0; wdt_reset(); update_leds(); + // Посылаем ключ metacom_send(key+1); - } else { + } else { // iButton + // После трёх попыток выключаемся if (t >= 2) return 0; + // Переходим в режим переговоров с дверью ibutton_wait_for_master(key); } @@ -424,7 +470,7 @@ int send_mode() update_leds_bright(); _delay_ms(1); t++; - if (t >= 1000 && !vezdehod_mode) return 1; // + if (t >= 1000 && !vezdehod_mode) return 1; // смена режима } break; } @@ -439,17 +485,17 @@ void sleep() onewire_init(); set_leds(0); UCSRB = 0; // disable USART - unset_bit(PORTD, 0); unset_bit(PORTD, 1); // USART + unset_bit(PORTD, 0); unset_bit(PORTD, 1); // Прижимаем USART к земле set_bit(DDRD, 0); set_bit(DDRD, 1); LINE_DISABLE; CYFRAL_PULLUP_DISABLE; CYFRAL_REFERENCE_DISABLE; - set_bit(MCUCR, SM1); unset_bit2(MCUCR, SM0, SM2); // Power-down - set_bit2(GICR, INT1, INT0); // + set_bit(MCUCR, SM1); unset_bit2(MCUCR, SM0, SM2); // Power-down спящий режим + set_bit2(GICR, INT1, INT0); // Включаем прерывания - set_bit(WDTCR, WDCE), unset_bit(WDTCR, WDE); // + set_bit(WDTCR, WDCE), unset_bit(WDTCR, WDE); // Собаку выключаем if (BUTTON_PRESSED || USB_POWERED) return; sleep_mode(); @@ -457,7 +503,7 @@ void sleep() int main (void) { - UCSRB = 0; // disable USART + UCSRB = 0; // Выключаем UART, из-за него ток утекает, куда не надо set_bit(LED1_DDR, LED1_PIN); // top led set_bit(LED2_DDR, LED2_PIN); // top-right led @@ -467,14 +513,14 @@ int main (void) set_bit(LED6_DDR, LED6_PIN); // top-left led set_bit(LED7_DDR, LED7_PIN); // center led - unset_bit(BUTTON_DDR, BUTTON_PIN); set_bit(BUTTON_OUT, BUTTON_PIN); // - unset_bit(USB_DETECT_DDR, USB_DETECT_PIN); set_bit(USB_DETECT_OUT, USB_DETECT_PIN); // USB - unset_bit(CYFRAL_PULLUP_DDR, CYFRAL_PULLUP_PIN); unset_bit(CYFRAL_PULLUP_OUT, CYFRAL_PULLUP_PIN); // 750 - set_bit(CYFRAL_REFERENCE_DDR, CYFRAL_REFERENCE_PIN); unset_bit(CYFRAL_REFERENCE_OUT, CYFRAL_REFERENCE_PIN); // - set_bit(LINE_ENABLE_DDR, LINE_ENABLE_PIN); unset_bit(LINE_ENABLE_OUT, LINE_ENABLE_PIN); // + unset_bit(BUTTON_DDR, BUTTON_PIN); set_bit(BUTTON_OUT, BUTTON_PIN); // Подтяжка кнопки + unset_bit(USB_DETECT_DDR, USB_DETECT_PIN); set_bit(USB_DETECT_OUT, USB_DETECT_PIN); // Подтяжка определения USB + unset_bit(CYFRAL_PULLUP_DDR, CYFRAL_PULLUP_PIN); unset_bit(CYFRAL_PULLUP_OUT, CYFRAL_PULLUP_PIN); // Подтяжка 750 Ом выключена + set_bit(CYFRAL_REFERENCE_DDR, CYFRAL_REFERENCE_PIN); unset_bit(CYFRAL_REFERENCE_OUT, CYFRAL_REFERENCE_PIN); // Делитель напряжения выключен + set_bit(LINE_ENABLE_DDR, LINE_ENABLE_PIN); unset_bit(LINE_ENABLE_OUT, LINE_ENABLE_PIN); // линия выключена onewire_init(); - // + // Лишние ноги прижимаем к земле set_bit(DDRC, 4); unset_bit(PORTC, 4); set_bit(DDRC, 5); unset_bit(PORTC, 5); set_bit(DDRD, 4); unset_bit(PORTD, 4); @@ -497,19 +543,19 @@ int main (void) while (1) { - set_bit(WDTCR, WDCE), set_bit(WDTCR, WDE); // - set_bit(WDTCR, WDCE), set_bit3(WDTCR, WDP2, WDP1, WDP0); // + set_bit(WDTCR, WDCE), set_bit(WDTCR, WDE); // Собака + set_bit(WDTCR, WDCE), set_bit3(WDTCR, WDP2, WDP1, WDP0); // Неспешащая собака int t = 0; vezdehod_mode = 0; do { - // + // При включении показываем бегущий по кругу светодиод for(b = 0; b < 6; b++) { //set_leds(1<