Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <avr/io.h>
- #include <avr/sleep.h>
- #include <avr/interrupt.h>
- #include <util/delay.h>
- #define wdt_reset() __asm__ __volatile__ ("wdr")
- #define _POWRPIN 0
- #define _PULLPIN 1
- #define _DATAPIN 2
- #define _DBUGPIN 3
- #define _RANDPIN 4
- // Адреса ведомых устройств.
- // 0, 3, 4, 5 и 6 байты одинаковы для всех: 0x3A, 0x01, 0x00, 0x00, 0x00.
- // 1, 2 и 7 байты:
- const uint8_t IDs [] [3] __attribute__ ((progmem)) =
- {
- {0x11, 0xE7, 0xF7},
- {0x8A, 0xE0, 0xEF},
- {0x57, 0xEA, 0xDC},
- {0x91, 0xDC, 0xE9},
- {0x75, 0xE1, 0x74},
- {0x56, 0xDE, 0x70},
- {0x93, 0xE9, 0xD1},
- {0x95, 0xDC, 0x35},
- {0x48, 0xE6, 0x82},
- {0xC3, 0xEC, 0x2D}
- };
- void blink (uint8_t num, uint8_t color);
- void onewire_reset (void);
- void onewire_tx (uint8_t data);
- // uint8_t onewire_rx (void);
- uint8_t randomize (void);
- uint8_t random (uint8_t);
- ISR (WDT_vect) // Обработчик прерывания по WDT
- {; // NOP
- }
- void main(void) __attribute__((noreturn));
- void main(void)
- {
- uint8_t rand1, rand2, color;
- register uint8_t seed, i;
- ACSR |= (1 << ACD); // отключить аналоговый компаратор
- seed = randomize ();
- if (!seed) // если seed=0, ГПСЧ не запустится
- {
- seed = 0x42; // почему 42? Ответ на Главный вопрос ;)
- }
- rand1 = random (seed);
- rand2 = random (0);
- wdt_reset();
- WDTCR |= (1<<WDCE) | (1<<WDE);
- // Настройка WDT на генерацию прерывания, тактирование CKwd/256K (период ~2 sec)
- WDTCR = (1<<WDTIE) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);
- set_sleep_mode (SLEEP_MODE_PWR_DOWN);
- sei();
- for (;;)
- {
- sleep_enable (); // в спячку
- cli(); // пробуждение по прерыванию
- color = rand1 >> 6;
- PORTB |= (1 << _PULLPIN); // _PULLPIN - "1"
- DDRB |= (1 << _PULLPIN); // _PULLPIN - out
- _delay_us (32);
- if (PINB & (1 << _DATAPIN)) // проверка на короткое замыкание шины
- {
- switch (rand2 >> 4) // выбор эффекта
- {
- case 0x01: // бегущий огонь слева направо ->
- i = 0;
- do
- {
- blink (i, color);
- } while (i++ < 9);
- break;
- case 0x02: // бегущий огонь справа налево <-
- i = 9;
- do
- {
- blink (i, color);
- } while (--i);
- break;
- case 0x03: // 3 вспышки
- blink ((rand2 & 0x07), color);
- case 0x04: // 2 вспышки
- blink (((rand1>>3) & 0x07) + 0x01, color);
- case 0x05: // 1 вспышка
- blink ((rand1 & 0x07) + 0x02, color);
- break;
- default: ; // отсутствие эффекта
- }
- }
- DDRB &= ~(1 << _PULLPIN); // _PULLPIN - in
- PORTB &= ~(1 << _PULLPIN); // _PULLPIN - z-state
- rand1 = random (0);
- rand2 = random (0);
- sei();
- }
- }
- void blink (uint8_t num, uint8_t color)
- {
- uint8_t* ptr;
- ptr = (uint8_t*) &(IDs [num][0]);
- register uint8_t i=3;
- onewire_reset ();
- onewire_tx (0x55); // match ROM
- onewire_tx (0x3A); // addr, byte 0
- onewire_tx (*ptr++); // addr, byte 1
- onewire_tx (*ptr++); // addr, byte 2
- onewire_tx (0x01); // addr, byte 3
- do
- {
- onewire_tx (0x00); // addr, byte 4, 5, 6
- } while (--i);
- onewire_tx (*ptr); // addr, byte 7
- onewire_tx (0x5A); // PIO access write
- onewire_tx (color); // switch on
- onewire_tx (~color); // подтверждение
- PORTB |= (1 << _POWRPIN); // _POWRPIN - "1"
- DDRB |= (1 << _POWRPIN); // _POWRPIN - out (pull up)
- _delay_ms (100);
- DDRB &= ~(1 << _POWRPIN); // _POWRPIN - in
- PORTB &= ~(1 << _POWRPIN); // _POWRPIN - z-state
- onewire_reset ();
- onewire_tx (0xA5); // Resume ROM
- onewire_tx (0x5A); // PIO access write
- onewire_tx (0x00); // switch off
- onewire_tx (0xFF); // подтверждение ~0x00
- }
- void onewire_reset (void)
- {
- PORTB &= ~(1 << _DATAPIN); // _DATAPIN - "0"
- DDRB |= (1 << _DATAPIN); // _DATAPIN - out (pull down)
- _delay_us (700);
- DDRB &= ~(1 << _DATAPIN); // _DATAPIN - in (tri-state)
- _delay_us (500);
- }
- void onewire_tx (uint8_t data)
- {
- register uint8_t i=8;
- do
- {
- if (data & 0x80)
- { // one
- DDRB |= (1 << _DATAPIN); // _DATAPIN - pull down
- _delay_us (6);
- DDRB &= ~(1 << _DATAPIN); // _DATAPIN - tri-state
- _delay_us (64);
- }
- else
- { // zero
- DDRB |= (1 << _DATAPIN); // _DATAPIN - pull down
- _delay_us (60);
- DDRB &= ~(1 << _DATAPIN); // _DATAPIN - tri-state
- _delay_us (10);
- }
- data <<= 1;
- }
- while (--i);
- }
- /*
- uint8_t onewire_rx (void)
- {
- uint8_t result = 0x00;
- register uint8_t i=8;
- do
- {
- result <<= 1;
- DDRB |= (1 << _DATAPIN); // _DATAPIN - pull down
- _delay_us (6);
- DDRB &= ~(1 << _DATAPIN); // _DATAPIN - tri-state
- _delay_us (9);
- if (PINB & (1 << _DATAPIN))
- {
- result |= 0x01;
- }
- _delay_us (55);
- }
- while (--i);
- return result;
- }
- */
- uint8_t randomize (void)
- {
- cli();
- TCCR0A = 0x00;
- TCCR0B = (1 << CS00); // запуск таймера T0, тактирование CK/1
- wdt_reset();
- WDTCR |= (1<<WDCE) | (1<<WDE);
- WDTCR = (1<<WDTIE); // настройка WDT на прерывание, тактирование CKwd/2K
- set_sleep_mode (SLEEP_MODE_IDLE);
- sei();
- sleep_enable (); // в спячку
- cli(); // пробуждение по прерыванию
- WDTCR |= (1<<WDCE) | (1<<WDE);
- WDTCR = 0x00;
- TCCR0B = 0x00; // остановить таймер
- return TCNT0;
- }
- uint8_t random (uint8_t seed)
- {
- // 15 bit linear feedback shift register
- static uint16_t lfsr;
- uint16_t bit;
- uint8_t result = 0x00;
- if (seed)
- { // инициализация
- lfsr = seed | ~(seed << 8);
- }
- register uint8_t i=8;
- do
- {
- result <<= 1;
- // характеристический полином: x^15 + x^14 + 1
- bit = ((lfsr >> 1) ^ (lfsr >> 2)) & 0x0001;
- lfsr = (lfsr >> 1) | (bit << 14);
- result |= bit;
- }
- while (--i);
- return result;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement