Guest User

Untitled

a guest
May 2nd, 2013
1,548
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. // Arduino Digital Light Wand + SD + LCD V1.07 (LPD8806)
  3. // by Is0-Mick 2012
  4. //
  5. // Added support for external control switches, for UP and Down to select the filename.
  6. //
  7. //
  8. // This version can use dual strips for double the resolution (change dualstrip = false to true)
  9. //
  10. // This version supports direct reading of a 24bit BMP from the SD card.
  11. // You need to rotate the image 90 degrees right, due to lack of memory / speed to process
  12. // this on the fly...
  13. //
  14. // Added Gamma Table from ada fruit code which gives better conversion of 24 bit to 21 bit
  15. // instead of just bitshifting values.
  16. // Also added version number to display on start up.
  17. //
  18. // Fixed a strange problem with 1 green pixel being left on if the last line of the image
  19. // or last pixel was not black. Apparently seems to be a known hardware / library bug...
  20. //
  21. // Tidied up code
  22. //
  23. // Fixed Backlight Problem
  24. //
  25. // Fixed the SD init problem (removing card, trying to send a file (which fails) now re-inits the card.
  26. // Backlight now fades out, instead of just switching off.
  27. //
  28. // Changed one of the original values of the shields key values, as it was thinking you were pressing a different
  29. // button sometimes, so changed the 535 value to 600 which seems to fix that :)
  30. //
  31. // Added code for an external switch to show the bitmap so you don't have fiddle with the small button on the shield
  32. // Pins are defined as aux button. I pulled one low as a GND, and the other is the trigger.(pins 44,45 currently)
  33.  
  34.  
  35.  
  36.  
  37. #include <LPD8806.h>
  38. #include <SD.h>
  39. #include <LiquidCrystal.h>
  40. #include <SPI.h>
  41.  
  42.  
  43. #define BACKLIGHT 10
  44. #define SDssPin 53  //SD card CS pin
  45. int frameDelay = 10; // default for the frame delay
  46. LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  //Init the LCD
  47.  
  48. int dataPin = 31;
  49. int clockPin = 32;
  50. byte gamma(byte x);
  51.  
  52.  
  53. #define STRIP_LENGTH 104
  54. boolean dualstrip = false;//set to true for dual strips
  55.  
  56. LPD8806 strip = LPD8806(STRIP_LENGTH, dataPin, clockPin);
  57.  
  58. //BacklightControl to save battery Life
  59. boolean BackLightTimer = false;
  60. int BackLightTimeout = 2000;
  61. int BackLightTemp =  BackLightTimeout;
  62.  
  63. //Stuff for the Keypad
  64. //int adc_key_val[5] ={
  65. //  30, 150, 360, 535, 760 };
  66.  
  67. int adc_key_val[5] ={
  68.   30, 150, 360, 600, 760 };  
  69. int NUM_KEYS = 5;
  70. int adc_key_in;
  71. int key=-1;
  72. int oldkey=-1;
  73.  
  74. //AuxButton is a seperate button to send the image. Connect wires to these pins to use it.
  75. int AuxButton = 44;
  76. int AuxButtonGND = 45;
  77.  
  78. //Up Button is a seperate button to move up the filenames. Connect wires to these pins to use it.
  79. int UpButton =42;
  80. int UpButtonGND = 43;
  81.  
  82. //Down Button is a seperate button to move down the filenames. Connect wires to these pins to use it.
  83. int DownButton =40;
  84. int DownButtonGND =41;
  85.  
  86. File root;
  87. File dataFile;
  88. String m_CurrentFilename = "";
  89. int m_FileIndex = 0;
  90. int m_NumberOfFiles = 0;
  91. String m_FileNames[200]; //yep this is bad, but unless you are going to have over 200 images on your lightwand..
  92.  
  93. long buffer[STRIP_LENGTH];
  94.  
  95. void setup()
  96. {
  97.   Serial.begin(115200);
  98.   pinMode(AuxButton, INPUT);
  99.   digitalWrite(AuxButton,HIGH);
  100.   pinMode(AuxButtonGND, OUTPUT);
  101.   digitalWrite(AuxButtonGND,LOW);
  102.  
  103.   pinMode(UpButton, INPUT);
  104.   digitalWrite(UpButton,HIGH);
  105.   pinMode(UpButtonGND, OUTPUT);
  106.   digitalWrite(UpButtonGND,LOW);
  107.  
  108.   pinMode(DownButton, INPUT);
  109.   digitalWrite(DownButton,HIGH);
  110.   pinMode(DownButtonGND, OUTPUT);
  111.   digitalWrite(DownButtonGND,LOW);
  112.   setupLEDs();
  113.   setupLCDdisplay();
  114.   setupSDcard();
  115.   BackLightOn();
  116. }
  117.  
  118. void setupLEDs()
  119. {
  120.   strip.begin();
  121.   strip.show();
  122. }
  123.  
  124. void setupLCDdisplay()
  125. {
  126.   lcd.begin(16,2);
  127.   lcd.print("*** DLW V.07 ***");
  128.   lcd.setCursor(0, 1);
  129.   lcd.print("Initializing...");
  130.   delay(1000);  
  131.   lcd.clear();
  132. }
  133.  
  134. void setupSDcard()
  135. {
  136.   pinMode(SDssPin, OUTPUT);
  137.  
  138.   while (!SD.begin(SDssPin)) {
  139.     BackLightOn();
  140.     lcd.print("SD init failed!");
  141.     delay(1000);
  142.     lcd.clear();
  143.     delay(500);
  144.   }
  145.   lcd.clear();
  146.   lcd.print("SD init done.");
  147.   delay(1000);
  148.   root = SD.open("/");
  149.   lcd.clear();
  150.   lcd.print("Scanning files");
  151.   delay(500);
  152.   GetFileNamesFromSD(root);
  153.   isort(m_FileNames, m_NumberOfFiles);
  154.   m_CurrentFilename = m_FileNames[0];
  155.   DisplayCurrentFilename();
  156.  
  157. }
  158.  
  159. int ReadKeypad()
  160. {
  161.   adc_key_in = analogRead(0);    // read the value from the sensor  
  162.   digitalWrite(13, HIGH);  
  163.   key = get_key(adc_key_in);                // convert into key press
  164.   //Serial.print("key read = ");
  165.   //Serial.println(adc_key_in,DEC);
  166.  
  167.   if (key != oldkey)                    // if keypress is detected
  168.   {
  169.     delay(50);      // wait for debounce time
  170.     adc_key_in = analogRead(0);    // read the value from the sensor  
  171.     key = get_key(adc_key_in);              // convert into key press
  172.     if (key != oldkey)             
  173.     {          
  174.       oldkey = key;
  175.       if (key >=0){
  176.         return key;
  177.       }
  178.     }
  179.   }
  180.   return key;
  181. }
  182.  
  183.  
  184. // Convert ADC value to key number
  185. int get_key(unsigned int input)
  186. {
  187.   int k;
  188.   for (k = 0; k < NUM_KEYS; k++)
  189.   {
  190.     if (input < adc_key_val[k])
  191.     {        
  192.       return k;
  193.     }
  194.   }
  195.   if (k >= NUM_KEYS)
  196.     k = -1;     // No valid key pressed
  197.   return k;
  198. }
  199.  
  200.  
  201. //The Main menu starts here...
  202. void loop()
  203. {
  204.   int keypress = ReadKeypad();
  205.   if (( keypress == 1) || (digitalRead(UpButton) == LOW)) //up key (step up through the filenames)
  206.   {
  207.     BackLightOn();
  208.     if (m_FileIndex > 0)
  209.     {
  210.       m_FileIndex--;
  211.     }
  212.     else
  213.     {
  214.       m_FileIndex = m_NumberOfFiles -1; //wrap round to the last file
  215.     }
  216.  
  217.     DisplayCurrentFilename();
  218.     delay(500);
  219.   }
  220.  
  221.   if (( keypress == 2) || (digitalRead(DownButton) == LOW)) //down key (step down through the filenames)
  222.   {
  223.     BackLightOn();
  224.     if (m_FileIndex < m_NumberOfFiles -1)
  225.     {
  226.       m_FileIndex++;
  227.     }
  228.     else
  229.     {
  230.       m_FileIndex = 0;//wrap round to the 1st file again
  231.     }
  232.     DisplayCurrentFilename();
  233.     delay(500);
  234.   }
  235.   //Serial.print(digitalRead(AuxButton),DEC);//for displaying the key values
  236.  
  237.   if ((keypress == 4) || (digitalRead(AuxButton) == LOW))//select key (send out the selected file)
  238.   {
  239.     SendFile(m_CurrentFilename);
  240.   }
  241.  
  242.   if(keypress == 0) //right key (frame delay +)
  243.   {
  244.     BackLightOn();
  245.     if (frameDelay < 200)
  246.     {
  247.       frameDelay+=5;
  248.     }
  249.     ShowFrameDelay();
  250.   }
  251.  
  252.   if(keypress == 3)//left key (frame delay -)
  253.   {
  254.     BackLightOn();
  255.     if (frameDelay > 5)
  256.     {
  257.       frameDelay-=5;
  258.     }
  259.     ShowFrameDelay();
  260.   }
  261.  
  262.   if (BackLightTimer == true) BackLightTime();
  263.  
  264. }
  265.  
  266. void BackLightOn()
  267. {
  268.   analogWrite(BACKLIGHT,255);
  269.   BackLightTimer = true;
  270.   BackLightTemp =  BackLightTimeout;
  271. }
  272.  
  273. void BackLightTime()
  274. {
  275.   if ((BackLightTemp <= 255) && (BackLightTemp >= 0))
  276.   {
  277.     analogWrite(BACKLIGHT,BackLightTemp);
  278.     delay(1);
  279.   }
  280.  
  281.   if (BackLightTemp <= 0)
  282.   {
  283.     BackLightTimer = false;
  284.     BackLightTemp =  BackLightTimeout;
  285.     analogWrite(BACKLIGHT,0);
  286.   }
  287.   else
  288.   {
  289.     BackLightTemp --;
  290.     delay(1);
  291.   }
  292. }
  293.  
  294. void ShowFrameDelay()
  295. {
  296.   lcd.clear();
  297.   lcd.print("Frame delay:");
  298.   lcd.setCursor(0,1);
  299.   lcd.print(frameDelay);
  300.   delay(500);
  301.   DisplayCurrentFilename();
  302. }
  303.  
  304.  
  305. void SendFile(String Filename)
  306. {
  307.   lcd.clear();
  308.   lcd.print("Sending File");
  309.   lcd.setCursor(0, 1);
  310.   lcd.print(Filename);
  311.   char temp[14];
  312.   Filename.toCharArray(temp,14);
  313.  
  314.   dataFile = SD.open(temp);
  315.  
  316.   // if the file is available send it to the LED's
  317.   if (dataFile)
  318.   {
  319.     ReadTheFile();
  320.     dataFile.close();
  321.     ClearStrip(100);
  322.   }  
  323.   else
  324.   {
  325.     lcd.clear();
  326.     lcd.print("  Error reading");
  327.     lcd.setCursor(4, 1);
  328.     lcd.print("file");
  329.     BackLightOn();
  330.     delay(1000);
  331.     lcd.clear();
  332.     setupSDcard();//try to re-init the SD card...(this was failing, but a fix can be done below)
  333.     //In the SD.CPP in the BEGIN class which starts
  334.     // boolean SDClass::begin(uint8_t csPin) {
  335.     //
  336.     //it needs the line below to be added
  337.     //
  338.     // if (root.isOpen()) root.close(); // allows repeated calls
  339.     //
  340.     // Just before the line
  341.     // return card.init(SPI_HALF_SPEED, csPin) &&
  342.     //
  343.     //
  344.  
  345.  
  346.     return;
  347.   }
  348.   DisplayCurrentFilename();
  349. }
  350.  
  351. void DisplayCurrentFilename()
  352. {
  353.   m_CurrentFilename = m_FileNames[m_FileIndex];
  354.   lcd.clear();
  355.   lcd.print(m_CurrentFilename);
  356. }
  357.  
  358. void GetFileNamesFromSD(File dir)
  359. {
  360.   int fileCount = 0;
  361.   String CurrentFilename = "";
  362.   while(1)
  363.   {
  364.     File entry =  dir.openNextFile();
  365.     if (! entry) {
  366.       // no more files
  367.       m_NumberOfFiles = fileCount;
  368.       break;
  369.     }
  370.     else
  371.     {
  372.       if (entry.isDirectory()) {
  373.         //GetNextFileName(root);
  374.       }
  375.       else {
  376.         CurrentFilename = entry.name();
  377.         if (CurrentFilename.endsWith(".bmp") || CurrentFilename.endsWith(".BMP") )//find files with our extension only
  378.         {
  379.           m_FileNames[fileCount] = entry.name();
  380.           fileCount++;
  381.         }
  382.       }
  383.     }
  384.   }
  385. }
  386.  
  387.  
  388. void latchanddelay(int dur)
  389. {
  390.   strip.show();
  391.   delay(dur);
  392. }
  393.  
  394. void ClearStrip(int duration)
  395. {
  396.   int x;
  397.   for(x=0;x<STRIP_LENGTH;x++)
  398.   {
  399.     strip.setPixelColor(x, 0);
  400.   }
  401.   strip.show();// Had to add this extra show, otherwise if you were displaying an image
  402.   // and the last line / pixel were white, a green pixel would remain lit!
  403.   latchanddelay(duration);
  404.  
  405. }
  406.  
  407. uint32_t readLong()
  408. {
  409.   uint32_t retValue;
  410.   byte incomingbyte;
  411.  
  412.   incomingbyte=readByte();
  413.   retValue=(uint32_t)((byte)incomingbyte);
  414.  
  415.   incomingbyte=readByte();
  416.   retValue+=(uint32_t)((byte)incomingbyte)<<8;
  417.  
  418.   incomingbyte=readByte();
  419.   retValue+=(uint32_t)((byte)incomingbyte)<<16;
  420.  
  421.   incomingbyte=readByte();
  422.   retValue+=(uint32_t)((byte)incomingbyte)<<24;
  423.  
  424.   return retValue;
  425. }
  426.  
  427. uint16_t readInt()
  428. {
  429.   byte incomingbyte;
  430.   uint16_t retValue;
  431.  
  432.   incomingbyte=readByte();
  433.   retValue+=(uint16_t)((byte)incomingbyte);
  434.  
  435.   incomingbyte=readByte();
  436.   retValue+=(uint16_t)((byte)incomingbyte)<<8;
  437.  
  438.   return retValue;
  439. }
  440.  
  441. int readByte()
  442. {
  443.   int retbyte=-1;
  444.   while(retbyte<0) retbyte= dataFile.read();
  445.   return retbyte;
  446. }
  447.  
  448.  
  449. void ReadTheFile()
  450. {
  451. #define MYBMP_BF_TYPE           0x4D42
  452. #define MYBMP_BF_OFF_BITS       54
  453. #define MYBMP_BI_SIZE           40
  454. #define MYBMP_BI_RGB            0L
  455. #define MYBMP_BI_RLE8           1L
  456. #define MYBMP_BI_RLE4           2L
  457. #define MYBMP_BI_BITFIELDS      3L
  458.  
  459.  
  460.  
  461.   uint16_t bmpType = readInt();
  462.   uint32_t bmpSize = readLong();
  463.   uint16_t bmpReserved1 = readInt();
  464.   uint16_t bmpReserved2 = readInt();
  465.   uint32_t bmpOffBits = readLong();
  466.   bmpOffBits = 54;
  467.  
  468.   Serial.println("bmpType = ");
  469.   Serial.println(bmpType,HEX);
  470.  
  471.   Serial.println("bmpSize");
  472.   Serial.println(bmpSize,DEC);
  473.  
  474.   Serial.println("bmpReserved1");
  475.   Serial.println(bmpReserved1,DEC);
  476.  
  477.   Serial.println("bmpReserved2");
  478.   Serial.println(bmpReserved2,DEC);
  479.  
  480.  
  481.   Serial.println("bmpOffBits");
  482.   Serial.println(bmpOffBits,DEC);
  483.  
  484.   /* Check file header */
  485.   if (bmpType != MYBMP_BF_TYPE || bmpOffBits != MYBMP_BF_OFF_BITS)
  486.   {
  487.     lcd.setCursor(0, 0);
  488.     lcd.print("not a bitmap");
  489.     delay(1000);
  490.     return;
  491.   }
  492.  
  493.   /* Read info header */
  494.   uint32_t imgSize = readLong();
  495.   uint32_t imgWidth = readLong();
  496.   uint32_t imgHeight = readLong();
  497.   uint16_t imgPlanes = readInt();
  498.   uint16_t imgBitCount = readInt();
  499.   uint32_t imgCompression = readLong();
  500.   uint32_t imgSizeImage = readLong();
  501.   uint32_t imgXPelsPerMeter = readLong();
  502.   uint32_t imgYPelsPerMeter = readLong();
  503.   uint32_t imgClrUsed = readLong();
  504.   uint32_t imgClrImportant = readLong();
  505.  
  506.  
  507.   Serial.println("bitmap height");
  508.   Serial.println(imgHeight,DEC);
  509.   Serial.println("bitmap Width");
  510.   Serial.println(imgWidth,DEC);
  511.   Serial.println("bitmap bpp");
  512.   Serial.println(imgBitCount,DEC);
  513.  
  514.   /* Check info header */
  515.   if( imgSize != MYBMP_BI_SIZE || imgWidth <= 0 ||
  516.     imgHeight <= 0 || imgPlanes != 1 ||
  517.     imgBitCount != 24 || imgCompression != MYBMP_BI_RGB ||
  518.     imgSizeImage == 0 )
  519.   {
  520.     lcd.setCursor(0, 0);
  521.     lcd.print("Unsupported");
  522.     lcd.setCursor(0, 1);
  523.     lcd.print("Bitmap Use 24bpp");
  524.     delay(1000);
  525.     return;
  526.   }
  527.  
  528.   int displayWidth = imgWidth;
  529.   if (imgWidth > STRIP_LENGTH)
  530.   {
  531.     displayWidth = STRIP_LENGTH;//only display the number of led's we have
  532.   }
  533.  
  534.  
  535.   /* compute the line length */
  536.   uint32_t lineLength = imgWidth * 3;
  537.   if ((lineLength % 4) != 0)
  538.     lineLength = (lineLength / 4 + 1) * 4;
  539.  
  540.   Serial.println("Line Length");
  541.   Serial.println(lineLength,DEC);
  542.  
  543.   int x = 0;
  544.   for(int y=imgHeight;y>0 ;y--) {
  545.  
  546.     int bufpos=0;    
  547.  
  548.  
  549.     if ( dualstrip == true)
  550.     {
  551.       int pos = 0;
  552.       for(int x=0;x <((displayWidth)/2) ;x ++) {
  553.  
  554.         uint32_t offset = (MYBMP_BF_OFF_BITS + (((y-1)* lineLength) + (pos*3))) ;
  555.         //Serial.println("x = ");
  556.         //Serial.println(x,DEC);
  557.         dataFile.seek(offset);
  558.  
  559.         int g=gamma(readByte());
  560.         int b=gamma(readByte());
  561.         int r=gamma(readByte());
  562.         strip.setPixelColor(x,r,g,b);
  563.  
  564.         g=gamma(readByte());
  565.         b=gamma(readByte());
  566.         r=gamma(readByte());
  567.         strip.setPixelColor((STRIP_LENGTH-x)-1,r,g,b);
  568.         pos+=2;
  569.  
  570.       }
  571.      
  572.       latchanddelay(frameDelay/2);
  573.      
  574.  
  575.     }
  576.     else
  577.     {
  578.       for(int x=0;x <displayWidth  ;x++) {
  579.  
  580.         uint32_t offset = (MYBMP_BF_OFF_BITS + (((y-1)* lineLength) + (x*3))) ;
  581.  
  582.         dataFile.seek(offset);
  583.  
  584.         int g=gamma(readByte());
  585.         int b=gamma(readByte());
  586.         int r=gamma(readByte());
  587.         strip.setPixelColor(x,r,g,b);
  588.  
  589.  
  590.       }
  591.        latchanddelay(frameDelay);
  592.     }
  593.    
  594.  
  595.   }
  596.   Serial.println("Finished");
  597.   ClearStrip(100);
  598. }
  599.  
  600. //sort the filenames in alphabetical order
  601. void isort(String *filenames, int n)
  602. {
  603.   for (int i = 1; i < n; ++i)
  604.   {
  605.     String j = filenames[i];
  606.     int k;
  607.     for (k = i - 1; (k >= 0) && (j < filenames[k]); k--)
  608.     {
  609.       filenames[k + 1] = filenames[k];
  610.     }
  611.     filenames[k + 1] = j;
  612.   }
  613. }
  614.  
  615. // Gamma correction compensates for our eyes' nonlinear perception of
  616. // intensity.  It's the LAST step before a pixel value is stored, and
  617. // allows intermediate rendering/processing to occur in linear space.
  618. // The table contains 256 elements (8 bit input), though the outputs are
  619. // only 7 bits (0 to 127).  This is normal and intentional by design: it
  620. // allows all the rendering code to operate in the more familiar unsigned
  621. // 8-bit colorspace (used in a lot of existing graphics code), and better
  622. // preserves accuracy where repeated color blending operations occur.
  623. // Only the final end product is converted to 7 bits, the native format
  624. // for the LPD8806 LED driver.  Gamma correction and 7-bit decimation
  625. // thus occur in a single operation.
  626. PROGMEM prog_uchar gammaTable[]  = {
  627.   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  628.   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
  629.   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,
  630.   2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,
  631.   4,  4,  4,  4,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  7,  7,
  632.   7,  7,  7,  8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11,
  633.   11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16,
  634.   16, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22,
  635.   23, 23, 24, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
  636.   30, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 37, 38, 38, 39,
  637.   40, 40, 41, 41, 42, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49, 50,
  638.   50, 51, 52, 52, 53, 54, 55, 55, 56, 57, 58, 58, 59, 60, 61, 62,
  639.   62, 63, 64, 65, 66, 67, 67, 68, 69, 70, 71, 72, 73, 74, 74, 75,
  640.   76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
  641.   92, 93, 94, 95, 96, 97, 98, 99,100,101,102,104,105,106,107,108,
  642.   109,110,111,113,114,115,116,117,118,120,121,122,123,125,126,127
  643. };
  644.  
  645.  
  646. inline byte gamma(byte x) {
  647.   return pgm_read_byte(&gammaTable[x]);
  648. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×