Advertisement
Guest User

Digital Light Wand + LCD + SD + HL1606 + BMP direct

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