Advertisement
Guest User

carlhako

a guest
Nov 14th, 2011
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.92 KB | None | 0 0
  1. #define F_CPU 14745600
  2.  
  3. #include <avr/io.h>
  4. #include <inttypes.h>
  5. #include <avr/interrupt.h>
  6. #include "../../libnerdkits/delay.h"
  7.  
  8. #include "../../libnerdkits/lcd.h"
  9. #include <avr/pgmspace.h>
  10.  
  11.  
  12. #define SER         PC0
  13. #define CLOCK   PC1
  14. #define LATCH       PC2
  15. #define PORT595     PORTC
  16. #define DDR595  DDRC
  17.  
  18. volatile uint8_t mode = 0;
  19. volatile uint16_t delay = 10; // initial delay
  20. volatile uint8_t number_of_strips = 3;
  21. // for some reason i cant dynamically set the size of an array based on the amount of shift registers. So i have hard set this to 30
  22. volatile uint8_t SHIFT_REGISTER[30]; // each 595 has its own 8bit var
  23.  
  24. volatile uint16_t fdelay[10]; // each strip has its own var in this array used for timing
  25. volatile uint16_t snowflakes = 0; // used to tally up the number of snowflakes to display on lcd
  26.  
  27.  
  28. //********************************************************************************************************
  29.  
  30. void high_shift() { // push out a 1
  31.     PORT595 |= (1<<SER);
  32.     PORT595 |= (1<<CLOCK);
  33.     PORT595 &= ~(1<<CLOCK);
  34.     PORT595 &= ~(1<<SER);
  35. }
  36.  
  37. //********************************************************************************************************
  38.  
  39. void low_shift() { // push out a 0
  40.     PORT595 |= (1<<CLOCK);
  41.     PORT595 &= ~(1<<CLOCK);
  42. }
  43.  
  44. //********************************************************************************************************
  45.  
  46. void latch() { // trigger latch
  47.     PORT595 |= (1<<LATCH);
  48.     PORT595 &= ~(1<<LATCH);
  49. }
  50.  
  51. //********************************************************************************************************
  52.  
  53. void shift_out(uint8_t data) { // push out 8 bits
  54.     uint8_t loop;
  55.     for (loop = 0; loop < 8; loop++) {
  56.         if (data & 0x01) high_shift();
  57.         else low_shift();
  58.         data >>= 1;
  59.     }
  60. }
  61.  
  62. //********************************************************************************************************
  63.  
  64. ISR(TIMER1_COMPA_vect) { //50hz timer which constantly shifts out led status
  65.     int8_t loop;
  66.     for (loop=(number_of_strips*3);loop>=0;loop--) {
  67.         shift_out(SHIFT_REGISTER[loop]);
  68.     }
  69.     for (loop=0;loop<number_of_strips;loop++) {
  70.         if (fdelay[loop] > 1) fdelay[loop]--;
  71.     }
  72.     latch();
  73. }
  74.  
  75. //********************************************************************************************************
  76.  
  77. void sync_strips() { // will sync all strips with the first one.
  78.  
  79.     uint8_t i;
  80.     for (i=0; i<(number_of_strips*3-3);i++) {
  81.         SHIFT_REGISTER[i+3] = SHIFT_REGISTER[i];
  82.     }
  83.  
  84. }
  85.  
  86. //********************************************************************************************************
  87.  
  88. void clear_strips() { // as it says clears all the strips
  89.  
  90.     SHIFT_REGISTER[0] = 0;
  91.     SHIFT_REGISTER[1] = 0;
  92.     SHIFT_REGISTER[2] = 0;
  93.     sync_strips();
  94.  
  95. }
  96.  
  97. //********************************************************************************************************
  98.  
  99. ISR(PCINT1_vect) { // external pin change interupt
  100.     //uint8_t debounce;
  101.    
  102.     uint8_t debounce = (debounce << 1) | ((PINC >> PC5) & 1);
  103.     if (debounce != 0xFF) {
  104.         while ((debounce != 0x00) && (debounce != 0xFF)) { // debounce and filter interference
  105.             debounce = (debounce << 1) | ((PINC >> PC5) & 1);
  106.             delay_ms(1);
  107.         }
  108.         if (!debounce) { // code to run if button was actually pressed and not interference
  109.             mode++;
  110.             update_lcd_top();
  111.         }
  112.         while (debounce != 0xFF) { // debounce
  113.             debounce = (debounce << 1) | ((PINC >> PC5) & 1);
  114.             delay_ms(1);
  115.         }
  116.     }
  117.    
  118.     debounce = (debounce << 1) | ((PINC >> PC4) & 1);
  119.     if (debounce != 0xFF) {
  120.         while ((debounce != 0x00) && (debounce != 0xFF)) { // debounce and filter interference
  121.             debounce = (debounce << 1) | ((PINC >> PC4) & 1);
  122.             delay_ms(1);
  123.         }
  124.         if (!debounce) { // code to run if button was actually pressed and not interference
  125.             if (delay > 1) delay -= 1;
  126.         }
  127.         while (debounce != 0xFF) { // debounce
  128.             debounce = (debounce << 1) | ((PINC >> PC4) & 1);
  129.             delay_ms(1);
  130.         }
  131.     }
  132.    
  133.     debounce = (debounce << 1) | ((PINC >> PC3) & 1);
  134.     if (debounce != 0xFF) {
  135.         while ((debounce != 0x00) && (debounce != 0xFF)) { // debounce and filter interference
  136.             debounce = (debounce << 1) | ((PINC >> PC3) & 1);
  137.             delay_ms(1);
  138.         }
  139.         if (!debounce) { // code to run if button was actually pressed and not interference
  140.             delay += 1;
  141.         }
  142.         while (debounce != 0xFF) { // debounce
  143.             debounce = (debounce << 1) | ((PINC >> PC3) & 1);
  144.             delay_ms(1);
  145.         }
  146.     }
  147. }
  148.  
  149. //********************************************************************************************************
  150.  
  151. void update_lcd_top() { // updates top row of the lcd
  152.     FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  153.     lcd_home();
  154.     lcd_write_string(PSTR("                ")); // clear it first
  155.     lcd_line_one();
  156.     fprintf_P(&lcd_stream, PSTR("Mode: %u Del: %u"), mode,delay);
  157. }
  158.  
  159. //********************************************************************************************************
  160. //********************************************************************************************************
  161. int main() {
  162.    
  163.     // start up the LCD
  164.     lcd_init();
  165.     FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  166.     lcd_home();
  167.  
  168.     //enable pin change interrupt
  169.     PCICR |= (1<<PCIE1);
  170.     PCMSK1 |= (1<<PCINT13)|(1<<PCINT12)|(1<<PCINT11);
  171.    
  172.     //Configure pin as input and enable pullup resistor for interupt
  173.     DDRC &= ~((1<<PC5)|(1<<PC4)|(1<<PC3));
  174.     PORTC |= (1<<PC5)|(1<<PC4)|(1<<PC3);
  175.  
  176.     // setup pins used for 595
  177.     DDR595 |= (1<<SER) | (1<<LATCH) | (1<<CLOCK);
  178.     PORT595 &= ~((1<<SER) | (1<<LATCH) | (1<<CLOCK));
  179.  
  180.     //Timer1 CK/1024 (14.4khz) clear timer on compare
  181.     TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS12)|(1<<CS10);
  182.     ICR1 = 287; // generates a 50hz interupt
  183.     TIMSK1 |= (1<<OCIE1A);
  184.        
  185.     sei();
  186.    
  187.     volatile uint8_t i;
  188.     volatile uint8_t status[10] = {0,0,0,0,0,0,0,0,0,0,0}; // because all the strips are  not synced each strip needs a status
  189.     volatile flake_size[10] = {0,0,0,0,0,0,0,0,0,0,0}; // used to randomly generate size of each flake
  190.  
  191.     update_lcd_top();
  192.    
  193.     while(1) {
  194.  
  195.         switch (mode)
  196.         {
  197.        
  198.             case 0:
  199.                
  200.                 /*
  201.                
  202.                 STATUS[i] STATES:
  203.                
  204.                 0 - start of loop, pick a random number before starting.
  205.                 1 - waiting for initial delay before starting
  206.                 2 - starting initial drop down of leds
  207.                 3 - snow flake falling
  208.                
  209.                 */
  210.                
  211.                 for (i=0; i<number_of_strips;i++) {
  212.                    
  213.                     if ((status[i] == 0) && (fdelay[i] == 0)) { // generate delay before starting snowflake
  214.                         status[i] = 1;
  215.                         fdelay[i] = rand() % (delay*20) + 1;
  216.                         flake_size[i] = rand() % 6 + 1;
  217.                     }
  218.                    
  219.                    
  220.                     if (status[i] == 1) { // wait for delay before starting snowflake
  221.                         if (fdelay[i] == 1) {
  222.                             status[i] = 2;
  223.                         }
  224.                     }
  225.                    
  226.                     if (status[i] == 2) { // start snowflak falling onto strip
  227.                         if (fdelay[i] == 1) { // internal delay
  228.                             SHIFT_REGISTER[i*3] = (SHIFT_REGISTER[i*3] >>1) | 0x80;
  229.                             fdelay[i] = delay;
  230.                             if (flake_size[i] == 1) if (SHIFT_REGISTER[i*3] == 0x80) status[i] = 3;
  231.                             if (flake_size[i] == 2) if (SHIFT_REGISTER[i*3] == 0xC0) status[i] = 3;
  232.                             if (flake_size[i] == 3) if (SHIFT_REGISTER[i*3] == 0xE0) status[i] = 3;
  233.                             if (flake_size[i] == 4) if (SHIFT_REGISTER[i*3] == 0xF0) status[i] = 3;
  234.                             if (flake_size[i] == 5) if (SHIFT_REGISTER[i*3] == 0xF8) status[i] = 3;
  235.                             if (flake_size[i] == 6) if (SHIFT_REGISTER[i*3] == 0xFC) status[i] = 3;
  236.                         }
  237.                     }
  238.                    
  239.                    
  240.                     if (status[i] == 3) { // make snowflake fall to bottom
  241.                         if (fdelay[i] == 1) {
  242.                             SHIFT_REGISTER[i*3+2] >>= 1; // shift 3rd register along
  243.                             if (SHIFT_REGISTER[i*3+1] & 0x01) SHIFT_REGISTER[i*3+2] |= 0x80; //if dot is at bottom of 2nd register light up the first one of 3rd register
  244.                             SHIFT_REGISTER[i*3+1] >>= 1; // shift 2nd register along
  245.                             if (SHIFT_REGISTER[i*3] & 0x01) SHIFT_REGISTER[i*3+1] |= 0x80; // if dot is at the bottom of 1st register light up the first one on 2nd register
  246.                             SHIFT_REGISTER[i*3] >>= 1; // shift first register long by 1
  247.                             fdelay[i] = delay;
  248.                             if ((SHIFT_REGISTER[i*3+2] == 0x00) && (SHIFT_REGISTER[i*3+1] == 0x00) && (SHIFT_REGISTER[i*3] == 0x00)) { // if all 3 are cleared start from the start again
  249.                                 status[i] = 0;
  250.                                 fdelay[i] = 0;
  251.                                 lcd_line_two();
  252.                                 lcd_write_string(PSTR("                "));
  253.                                 lcd_line_two();
  254.                                 fprintf_P(&lcd_stream, PSTR("Snowflakes: %u"), ++snowflakes);
  255.                             }
  256.                         }
  257.                     }
  258.                 }
  259.                    
  260.                
  261.                 break;
  262.                
  263.                
  264.             case 1: // all these cases will run the code below.
  265.             case 2: // all snowflakes are the same size depending on mode.
  266.             case 3: // below code is almost the same as above. only change is when status goes from 2 to 3.
  267.             case 4:
  268.             case 5:
  269.                
  270.                 /*
  271.                 STATUS[i] STATES:
  272.                
  273.                 0 - start of loop, pick a random number before starting.
  274.                 1 - waiting for initial delay before starting
  275.                 2 - starting initial drop down of leds
  276.                 3 - snow flake falling
  277.                
  278.                 */
  279.                
  280.                 for (i=0; i<number_of_strips;i++) {
  281.                    
  282.                     if ((status[i] == 0) && (fdelay[i] == 0)) { // generate delay before starting snowflake
  283.                         status[i] = 1;
  284.                         fdelay[i] = rand() % (delay*20) + 1;
  285.                         flake_size[i] = rand() % 4 + 1;
  286.                     }
  287.                    
  288.                    
  289.                     if (status[i] == 1) { // wait for delay before starting snowflake
  290.                         if (fdelay[i] == 1) {
  291.                             status[i] = 2;
  292.                         }
  293.                     }
  294.                    
  295.                     if (status[i] == 2) { // start snowflak falling onto strip
  296.                         if (fdelay[i] == 1) { // internal delay
  297.                             SHIFT_REGISTER[i*3] = (SHIFT_REGISTER[i*3] >>1) | 0x80;
  298.                             fdelay[i] = delay;
  299.                             if (mode == 1) if (SHIFT_REGISTER[i*3] == 0x80) status[i] = 3;
  300.                             if (mode == 2) if (SHIFT_REGISTER[i*3] == 0xC0) status[i] = 3;
  301.                             if (mode == 3) if (SHIFT_REGISTER[i*3] == 0xE0) status[i] = 3;
  302.                             if (mode == 4) if (SHIFT_REGISTER[i*3] == 0xF0) status[i] = 3;
  303.                             if (mode == 5) if (SHIFT_REGISTER[i*3] == 0xF8) status[i] = 3;
  304.                         }
  305.                     }
  306.                    
  307.                    
  308.                     if (status[i] == 3) {
  309.                         if (fdelay[i] == 1) {
  310.                             SHIFT_REGISTER[i*3+2] >>= 1; // shift 3rd register along
  311.                             if (SHIFT_REGISTER[i*3+1] & 0x01) SHIFT_REGISTER[i*3+2] |= 0x80; //if dot is at bottom of 2nd register light up the first one of 3rd register
  312.                             SHIFT_REGISTER[i*3+1] >>= 1; // shift 2nd register along
  313.                             if (SHIFT_REGISTER[i*3] & 0x01) SHIFT_REGISTER[i*3+1] |= 0x80; // if dot is at the bottom of 1st register light up the first one on 2nd register
  314.                             SHIFT_REGISTER[i*3] >>= 1; // shift first register long by 1
  315.                             fdelay[i] = delay;
  316.                             if ((SHIFT_REGISTER[i*3+2] == 0x00) && (SHIFT_REGISTER[i*3+1] == 0x00) && (SHIFT_REGISTER[i*3] == 0x00)) {// if all 3 are cleared start from the start again
  317.                                 status[i] = 0;
  318.                                 fdelay[i] = 0;
  319.                                 lcd_line_two();
  320.                                 lcd_write_string(PSTR("                "));
  321.                                 lcd_line_two();
  322.                                 fprintf_P(&lcd_stream, PSTR("Snowflakes: %u"), ++snowflakes);
  323.                             }
  324.                         }
  325.                     }
  326.                 }
  327.                    
  328.                
  329.             break;
  330.            
  331.             default:
  332.                 clear_strips();
  333.                 mode = 0;
  334.                 update_lcd_top();
  335.             break;
  336.         }
  337.        
  338.     }  
  339.       return 0;
  340. }
  341.  
  342.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement