Advertisement
Guest User

Untitled

a guest
Mar 18th, 2018
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.74 KB | None | 0 0
  1.  
  2. /*
  3.  This is an example of how simple driving a Neopixel can be
  4.  This code is optimized for understandability and changability rather than raw speed
  5.  More info at http://wp.josh.com/2014/05/11/ws2812-neopixels-made-easy/
  6. */
  7.  
  8. // Change this to be at least as long as your pixel string (too long will work fine, just be a little slower)
  9.  
  10. #define PIXELS 16  // Number of pixels in the string
  11.  
  12. // These values depend on which pin your string is connected to and what board you are using
  13. // More info on how to find these at http://www.arduino.cc/en/Reference/PortManipulation
  14.  
  15. // These values are for the pin that connects to the Data Input pin on the LED strip. They correspond to...
  16.  
  17. // Arduino Yun:     Digital Pin 8
  18. // DueMilinove/UNO: Digital Pin 12
  19. // Arduino MeagL    PWM Pin 4
  20.  
  21. // You'll need to look up the port/bit combination for other boards.
  22.  
  23. // Note that you could also include the DigitalWriteFast header file to not need to to this lookup.
  24.  
  25. #define PIXEL_PORT  PORTB  // Port of the pin the pixels are connected to
  26. #define PIXEL_DDR   DDRB   // Port of the pin the pixels are connected to
  27. #define PIXEL_BIT   4      // Bit of the pin the pixels are connected to
  28.  
  29. // These are the timing constraints taken mostly from the WS2812 datasheets
  30. // These are chosen to be conservative and avoid problems rather than for maximum throughput
  31.  
  32. #define T1H  900    // Width of a 1 bit in ns
  33. #define T1L  600    // Width of a 1 bit in ns
  34.  
  35. #define T0H  400    // Width of a 0 bit in ns
  36. #define T0L  900    // Width of a 0 bit in ns
  37.  
  38. #define RES 6000    // Width of the low gap between bits to cause a frame to latch
  39.  
  40. // Here are some convience defines for using nanoseconds specs to generate actual CPU delays
  41.  
  42. #define NS_PER_SEC (1000000000L)          // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
  43.  
  44. #define CYCLES_PER_SEC (F_CPU)
  45.  
  46. #define NS_PER_CYCLE ( NS_PER_SEC / CYCLES_PER_SEC )
  47.  
  48. #define NS_TO_CYCLES(n) ( (n) / NS_PER_CYCLE )
  49.  
  50. // Actually send a bit to the string. We must to drop to asm to enusre that the complier does
  51. // not reorder things and make it so the delay happens in the wrong place.
  52.  
  53. inline void sendBit( bool bitVal ) {
  54.  
  55.     if (  bitVal ) {        // 0 bit
  56.      
  57.     asm volatile (
  58.       "sbi %[port], %[bit] \n\t"        // Set the output bit
  59.       ".rept %[onCycles] \n\t"                                // Execute NOPs to delay exactly the specified number of cycles
  60.       "nop \n\t"
  61.       ".endr \n\t"
  62.       "cbi %[port], %[bit] \n\t"                              // Clear the output bit
  63.       ".rept %[offCycles] \n\t"                               // Execute NOPs to delay exactly the specified number of cycles
  64.       "nop \n\t"
  65.       ".endr \n\t"
  66.       ::
  67.       [port]    "I" (_SFR_IO_ADDR(PIXEL_PORT)),
  68.       [bit]   "I" (PIXEL_BIT),
  69.       [onCycles]  "I" (NS_TO_CYCLES(T1H) - 2),    // 1-bit width less overhead  for the actual bit setting, note that this delay could be longer and everything would still work
  70.       [offCycles]   "I" (NS_TO_CYCLES(T1L) - 2)     // Minimum interbit delay. Note that we probably don't need this at all since the loop overhead will be enough, but here for correctness
  71.  
  72.     );
  73.                                  
  74.     } else {          // 1 bit
  75.  
  76.     // **************************************************************************
  77.     // This line is really the only tight goldilocks timing in the whole program!
  78.     // **************************************************************************
  79.  
  80.  
  81.     asm volatile (
  82.       "sbi %[port], %[bit] \n\t"        // Set the output bit
  83.       ".rept %[onCycles] \n\t"        // Now timing actually matters. The 0-bit must be long enough to be detected but not too long or it will be a 1-bit
  84.       "nop \n\t"                                              // Execute NOPs to delay exactly the specified number of cycles
  85.       ".endr \n\t"
  86.       "cbi %[port], %[bit] \n\t"                              // Clear the output bit
  87.       ".rept %[offCycles] \n\t"                               // Execute NOPs to delay exactly the specified number of cycles
  88.       "nop \n\t"
  89.       ".endr \n\t"
  90.       ::
  91.       [port]    "I" (_SFR_IO_ADDR(PIXEL_PORT)),
  92.       [bit]   "I" (PIXEL_BIT),
  93.       [onCycles]  "I" (NS_TO_CYCLES(T0H) - 2),
  94.       [offCycles] "I" (NS_TO_CYCLES(T0L) - 2)
  95.  
  96.     );
  97.      
  98.     }
  99.    
  100.     // Note that the inter-bit gap can be as long as you want as long as it doesn't exceed the 5us reset timeout (which is A long time)
  101.     // Here I have been generous and not tried to squeeze the gap tight but instead erred on the side of lots of extra time.
  102.     // This has thenice side effect of avoid glitches on very long strings becuase
  103.  
  104.    
  105. }  
  106.  
  107.  
  108. inline void sendByte( unsigned char byte ) {
  109.    
  110.     for( unsigned char bit = 0 ; bit < 8 ; bit++ ) {
  111.      
  112.       sendBit( bitRead( byte , 7 ) );                // Neopixel wants bit in highest-to-lowest order
  113.                                                      // so send highest bit (bit #7 in an 8-bit byte since they start at 0)
  114.       byte <<= 1;                                    // and then shift left so bit 6 moves into 7, 5 moves into 6, etc
  115.      
  116.     }          
  117. }
  118.  
  119. /*
  120.  
  121.   The following three functions are the public API:
  122.  
  123.   ledSetup() - set up the pin that is connected to the string. Call once at the begining of the program.  
  124.   sendPixel( r g , b ) - send a single pixel to the string. Call this once for each pixel in a frame.
  125.   show() - show the recently sent pixel on the LEDs . Call once per frame.
  126.  
  127. */
  128.  
  129.  
  130. // Set the specified pin up as digital out
  131.  
  132. void ledsetup() {
  133.  
  134.   bitSet( PIXEL_DDR , PIXEL_BIT );
  135.  
  136. }
  137.  
  138. inline void sendPixel( unsigned char r, unsigned char g , unsigned char b )  {  
  139.  
  140.   sendByte(g);          // Neopixel wants colors in green then red then blue order
  141.   sendByte(r);
  142.   sendByte(b);
  143.  
  144. }
  145.  
  146.  
  147. // Just wait long enough without sending any bots to cause the pixels to latch and display the last sent frame
  148.  
  149. void show() {
  150.   _delay_us( (RES / 1000UL) + 1);       // Round up since the delay must be _at_least_ this long (too short might not work, too long not a problem)
  151. }
  152.  
  153. //-------------------------------------------------------------------------------------------------------------
  154.  
  155. void setPixelColor(int n, int r, int g, int b) {
  156.   cli();
  157.   for(int i = 0; i < PIXELS; i++) {
  158.     if (i == n) {
  159.       sendPixel(r, g, b);
  160.     } else {
  161.       sendPixel(0, 0, 0);
  162.     }
  163.   }
  164.   sei();
  165.   show();
  166. }
  167.  
  168. void setup() {
  169.   ledsetup();
  170.   showColor(0, 0, 0);
  171.   delay(300);
  172. }
  173.  
  174. void loop() {
  175.   for(int i = 0; i < PIXELS; i++) {
  176.     setPixelColor(i, 10, 10, 10);
  177.     delay(10);
  178.   }
  179.   for(int i = PIXELS - 1; i >= 0; i--) {
  180.     setPixelColor(i, 10, 10, 10);
  181.     delay(10);
  182.   }
  183. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement