Advertisement
Ocelot

LED necklace

Mar 1st, 2012
790
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.02 KB | None | 0 0
  1. #include <avr/io.h>
  2. #include <avr/sleep.h>
  3. #include <avr/interrupt.h>
  4. #include <util/delay.h>
  5.  
  6. #define wdt_reset() __asm__ __volatile__ ("wdr")
  7.  
  8. #define _POWRPIN 0
  9. #define _PULLPIN 1
  10. #define _DATAPIN 2
  11. #define _DBUGPIN 3
  12. #define _RANDPIN 4
  13.  
  14. // Адреса ведомых устройств.
  15. // 0, 3, 4, 5 и 6 байты одинаковы для всех: 0x3A, 0x01, 0x00, 0x00, 0x00.
  16. // 1, 2 и 7 байты:
  17. const uint8_t IDs [] [3] __attribute__ ((progmem)) =
  18. {  
  19.     {0x11, 0xE7, 0xF7},
  20.     {0x8A, 0xE0, 0xEF},
  21.     {0x57, 0xEA, 0xDC},
  22.     {0x91, 0xDC, 0xE9},
  23.     {0x75, 0xE1, 0x74},
  24.     {0x56, 0xDE, 0x70},
  25.     {0x93, 0xE9, 0xD1},
  26.     {0x95, 0xDC, 0x35},
  27.     {0x48, 0xE6, 0x82},
  28.     {0xC3, 0xEC, 0x2D}
  29. };
  30.  
  31. void    blink       (uint8_t num, uint8_t color);
  32. void    onewire_reset (void);
  33. void    onewire_tx  (uint8_t data);
  34. // uint8_t onewire_rx   (void);
  35. uint8_t randomize   (void);
  36. uint8_t random      (uint8_t);
  37.  
  38. ISR (WDT_vect)  // Обработчик прерывания по WDT
  39. {;  // NOP
  40. }
  41.  
  42. void main(void) __attribute__((noreturn));
  43.  
  44. void main(void)
  45. {
  46.     uint8_t rand1, rand2, color;
  47.     register uint8_t seed, i;
  48.    
  49.     ACSR |= (1 << ACD);     // отключить аналоговый компаратор
  50.     seed = randomize ();    
  51.     if (!seed)              // если seed=0, ГПСЧ не запустится
  52.     {
  53.         seed = 0x42;        // почему 42? Ответ на Главный вопрос ;)
  54.     }
  55.     rand1 = random (seed); 
  56.     rand2 = random (0);
  57.     wdt_reset();
  58.     WDTCR |= (1<<WDCE) | (1<<WDE);
  59.     // Настройка WDT на генерацию прерывания, тактирование CKwd/256K (период ~2 sec)
  60.     WDTCR = (1<<WDTIE) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);
  61.     set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  62.     sei();
  63.        
  64.     for (;;)
  65.     {
  66.         sleep_enable ();    // в спячку
  67.         cli();              // пробуждение по прерыванию
  68.         color = rand1 >> 6;
  69.         PORTB |= (1 << _PULLPIN);   // _PULLPIN - "1"
  70.         DDRB  |= (1 << _PULLPIN);   // _PULLPIN - out      
  71.         _delay_us (32);
  72.         if (PINB & (1 << _DATAPIN)) // проверка на короткое замыкание шины
  73.         {      
  74.             switch (rand2 >> 4) // выбор эффекта
  75.             {
  76.                 case 0x01:      // бегущий огонь слева направо ->
  77.                     i = 0;
  78.                     do
  79.                     {
  80.                         blink (i, color);
  81.                     } while (i++ < 9);
  82.                 break;
  83.                
  84.                 case 0x02:      // бегущий огонь справа налево <-
  85.                     i = 9;
  86.                     do
  87.                     {
  88.                         blink (i, color);
  89.                     } while (--i);                     
  90.                 break;
  91.                
  92.                 case 0x03:      // 3 вспышки
  93.                     blink ((rand2 & 0x07), color);
  94.                 case 0x04:      // 2 вспышки
  95.                     blink (((rand1>>3) & 0x07) + 0x01, color);
  96.                 case 0x05:      // 1 вспышка
  97.                     blink ((rand1 & 0x07) + 0x02, color);
  98.                 break;             
  99.                    
  100.                 default: ;      // отсутствие эффекта
  101.             }      
  102.         }
  103.         DDRB  &= ~(1 << _PULLPIN);  // _PULLPIN - in
  104.         PORTB &= ~(1 << _PULLPIN);  // _PULLPIN - z-state
  105.         rand1 = random (0);
  106.         rand2 = random (0);
  107.         sei();
  108.     }
  109. }
  110.  
  111. void blink (uint8_t num, uint8_t color)
  112. {
  113.     uint8_t* ptr;
  114.     ptr = (uint8_t*) &(IDs [num][0]);
  115.     register uint8_t i=3;
  116.     onewire_reset ();
  117.     onewire_tx  (0x55);     // match ROM
  118.     onewire_tx  (0x3A);     // addr, byte 0
  119.     onewire_tx  (*ptr++);   // addr, byte 1
  120.     onewire_tx  (*ptr++);   // addr, byte 2
  121.     onewire_tx  (0x01);     // addr, byte 3
  122.     do
  123.     {
  124.         onewire_tx  (0x00); // addr, byte 4, 5, 6
  125.     } while (--i);
  126.     onewire_tx  (*ptr);     // addr, byte 7
  127.     onewire_tx  (0x5A);     // PIO access write
  128.     onewire_tx  (color);    // switch on
  129.     onewire_tx  (~color);   // подтверждение
  130.    
  131.     PORTB |= (1 << _POWRPIN);   // _POWRPIN - "1"
  132.     DDRB  |= (1 << _POWRPIN);   // _POWRPIN - out (pull up)
  133.    
  134.     _delay_ms (100);
  135.    
  136.     DDRB  &= ~(1 << _POWRPIN);  // _POWRPIN - in
  137.     PORTB &= ~(1 << _POWRPIN);  // _POWRPIN - z-state
  138.  
  139.     onewire_reset ();
  140.     onewire_tx  (0xA5);     // Resume ROM
  141.     onewire_tx  (0x5A);     // PIO access write
  142.     onewire_tx  (0x00);     // switch off
  143.     onewire_tx  (0xFF);     // подтверждение ~0x00
  144. }
  145.  
  146. void onewire_reset (void)
  147. {
  148.     PORTB &= ~(1 << _DATAPIN);  // _DATAPIN - "0"
  149.     DDRB  |= (1 << _DATAPIN);   // _DATAPIN - out (pull down)
  150.     _delay_us (700);
  151.     DDRB  &= ~(1 << _DATAPIN);  // _DATAPIN - in (tri-state)
  152.     _delay_us (500);
  153. }
  154.  
  155. void onewire_tx (uint8_t data)
  156. {
  157.     register uint8_t i=8;
  158.     do
  159.     {
  160.         if (data & 0x80)
  161.         {       // one
  162.             DDRB  |= (1 << _DATAPIN);   // _DATAPIN - pull down
  163.             _delay_us (6);
  164.             DDRB  &= ~(1 << _DATAPIN);  // _DATAPIN - tri-state
  165.             _delay_us (64);
  166.         }
  167.         else
  168.         {       // zero
  169.             DDRB  |= (1 << _DATAPIN);   // _DATAPIN - pull down
  170.             _delay_us (60);
  171.             DDRB  &= ~(1 << _DATAPIN);  // _DATAPIN - tri-state
  172.             _delay_us (10);
  173.         }
  174.         data <<= 1;
  175.     }
  176.     while (--i);
  177. }
  178.  
  179. /*
  180. uint8_t onewire_rx (void)
  181. {
  182.     uint8_t result = 0x00;
  183.     register uint8_t i=8;
  184.     do
  185.     {
  186.         result <<= 1;
  187.         DDRB  |= (1 << _DATAPIN);   // _DATAPIN - pull down
  188.         _delay_us (6);
  189.         DDRB  &= ~(1 << _DATAPIN);  // _DATAPIN - tri-state
  190.         _delay_us (9);
  191.         if (PINB & (1 << _DATAPIN))
  192.         {
  193.             result |= 0x01;
  194.         }
  195.         _delay_us (55);
  196.     }
  197.     while (--i);
  198.     return result;
  199. }
  200. */
  201.  
  202. uint8_t randomize   (void)
  203. {
  204.     cli();
  205.     TCCR0A = 0x00;
  206.     TCCR0B = (1 << CS00);   // запуск таймера T0, тактирование CK/1
  207.     wdt_reset();
  208.     WDTCR |= (1<<WDCE) | (1<<WDE);
  209.     WDTCR = (1<<WDTIE);     // настройка WDT на прерывание, тактирование CKwd/2K
  210.     set_sleep_mode (SLEEP_MODE_IDLE);
  211.     sei();
  212.     sleep_enable ();    // в спячку
  213.     cli();              // пробуждение по прерыванию
  214.     WDTCR |= (1<<WDCE) | (1<<WDE);
  215.     WDTCR = 0x00;
  216.     TCCR0B = 0x00;      // остановить таймер
  217.     return TCNT0;
  218. }
  219.  
  220.  
  221. uint8_t random  (uint8_t seed)
  222. {
  223.     // 15 bit linear feedback shift register
  224.     static uint16_t lfsr;
  225.     uint16_t bit;
  226.     uint8_t result = 0x00;
  227.     if (seed)
  228.     {   // инициализация
  229.         lfsr = seed | ~(seed << 8);
  230.     }
  231.     register uint8_t i=8;
  232.     do
  233.     {
  234.         result <<= 1;
  235.         // характеристический полином: x^15 + x^14 + 1
  236.         bit  = ((lfsr >> 1) ^ (lfsr >> 2)) & 0x0001;
  237.         lfsr =  (lfsr >> 1) | (bit << 14);
  238.         result |= bit;
  239.     }
  240.     while (--i);   
  241.     return result;
  242. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement