A neopixel light painting strip

Dependencies:   NeoStrip PinDetect mbed

Files at this revision

API Documentation at this revision

Comitter:
lz307
Date:
Tue Nov 10 21:28:51 2015 +0000
Commit message:
Initial commit

Changed in this revision

BitmapFile.cpp Show annotated file Show diff for this revision Revisions of this file
BitmapFile.h Show annotated file Show diff for this revision Revisions of this file
NeoStrip.lib Show annotated file Show diff for this revision Revisions of this file
PinDetect.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BitmapFile.cpp	Tue Nov 10 21:28:51 2015 +0000
@@ -0,0 +1,287 @@
+#include "BitmapFile.h"
+
+
+BitmapFile::BitmapFile(char* fname) : m_pFile(NULL)
+{
+	m_fileName = fname;
+	Initialize();
+}
+
+BitmapFile::~BitmapFile()
+{
+	delete[] m_fileName;
+}
+
+bool BitmapFile::Initialize()
+{
+	bool success = true;
+	open();
+	fread(&BMPHeader,sizeof(BMPHeader),1,m_pFile);
+	success = (BMPHeader.b == 'B' && BMPHeader.m == 'M');
+	
+	fread(&m_headerlength,sizeof(m_headerlength),1,m_pFile);
+	fread(&DIBHeader,m_headerlength,1,m_pFile);
+	
+	/*Debugging code*/
+	
+	Serial pc2(USBTX,USBRX);
+	
+	pc2.printf("\n\rFile = %s", m_fileName);
+	
+	pc2.printf("\n\rBMPHeader - Size = %d:\n\r",sizeof(BMPHeader));
+	pc2.printf("\tbm:\t\t%c%c\n\r",BMPHeader.b,BMPHeader.m);
+	pc2.printf("\tfilesize:\t%d\n\r",BMPHeader.filesize);
+	pc2.printf("\treserved:\t%d,%d\n\r",BMPHeader.reserved1,BMPHeader.reserved2);
+	pc2.printf("\toffset:\t\t%d\n\r",BMPHeader.offset);
+	
+	pc2.printf("\n\rDIBHeader - Size = %d:\n\r",sizeof(DIBHeader));
+	//pc2.printf("\theaderLength:\t%d\n\r",DIBHeader.headerLength);
+	pc2.printf("\theight:\t\t\t%d\n\r",DIBHeader.height);
+	pc2.printf("\twidth:\t\t%d\n\r",DIBHeader.width);
+	pc2.printf("\tcplanes:\t\t%d\n\r",DIBHeader.cplanes);
+	pc2.printf("\tcolordepth:\t\t%d\n\r",DIBHeader.colordepth);
+	pc2.printf("\tcompression:\t%d\n\r",DIBHeader.compression);
+	pc2.printf("\tdatasize:\t\t%d\n\r",DIBHeader.datasize);
+	pc2.printf("\tvres:\t\t%d\n\r",DIBHeader.vres);
+	pc2.printf("\thres:\t\t%d\n\r",DIBHeader.hres);
+	
+	
+	
+	m_rowsize = 4*((getColorDepth()*getWidth()+31)/32);
+	
+	close();
+	return success;
+}
+
+void BitmapFile::open()
+{
+	if(m_pFile==NULL)
+	{
+		m_pFile = fopen(m_fileName, "r");
+	}
+}
+
+void BitmapFile::close()
+{
+	if(m_pFile!=NULL)
+	{
+		fclose(m_pFile);
+		m_pFile = NULL;
+	}
+}
+
+/**********************************************************/
+/*BMP Header Gets                                         */
+/**********************************************************/
+
+int BitmapFile::getFileSize()
+{
+	return BMPHeader.filesize;
+}
+
+int BitmapFile::getReserved1()
+{
+	return BMPHeader.reserved1;
+}
+
+int BitmapFile::getReserved2()
+{
+	return BMPHeader.reserved2;
+}
+
+int BitmapFile::getOffset()
+{
+	return BMPHeader.offset;
+}
+
+/**********************************************************/
+/*DIB Header Gets                                         */
+/**********************************************************/
+
+int BitmapFile::getHeaderType()
+{
+	return m_headerlength;
+}
+
+int BitmapFile::getHeight()
+{
+	return DIBHeader.height;
+}
+
+int BitmapFile::getWidth()
+{
+	return DIBHeader.width;
+}
+
+int BitmapFile::getCPlanes()
+{
+	return DIBHeader.cplanes;
+}
+
+int BitmapFile::getColorDepth()
+{
+	return DIBHeader.colordepth;
+}
+
+int BitmapFile::getCompression()
+{
+	return DIBHeader.compression;
+}
+
+int BitmapFile::getDataSize()
+{
+	return DIBHeader.datasize;
+}
+
+int BitmapFile::getHRes()
+{
+	return DIBHeader.hres;
+}
+
+int BitmapFile::getVRes()
+{
+	return DIBHeader.vres;
+}
+
+int BitmapFile::getNumPaletteColors()
+{
+	return DIBHeader.numpalettecolors;
+}
+
+int BitmapFile::getImportantColors()
+{
+	return DIBHeader.importantcolors;
+}
+
+/**********************************************************/
+/*Data Gets                                               */
+/**********************************************************/
+
+int BitmapFile::getRowSize()
+{
+	return m_rowsize;
+}
+
+int BitmapFile::getPixel(int row, int col, bool closefile)
+{
+	int color = -1;
+	if(row>=0 && row < getHeight() && col>=0 && col< getWidth())
+	{
+		if(getColorDepth() == 24)
+		{
+			open();
+			color = 0;	//make sure the last byte is 00
+			
+			int index = getOffset();
+			index += col*3;
+			index += row*4*ceil(getWidth()*3/4.0);
+			fseek(m_pFile, index, SEEK_SET);
+			
+			fread (&color, 3,1,m_pFile);
+			
+			if(closefile)
+			{
+				close();
+			}
+		}
+	}
+	return color;
+}
+
+int *BitmapFile::getRow(int row, bool closefile)
+{
+	open();
+	int *colors = new int[getWidth()];
+	int index = getOffset() + m_rowsize*row;
+	fseek(m_pFile, index, SEEK_SET);
+	if(getColorDepth() == 24)
+	{
+		for(int i=0; i<getWidth(); i++)
+		{
+			fread(&colors[i],3,1,m_pFile);
+		}
+	}
+	else if(getColorDepth() == 1)
+	{
+		char *temp = new char[m_rowsize];
+		for(int i=0; i<m_rowsize; i++)
+		{
+			fread(&temp[i],sizeof(char),1,m_pFile);
+		}
+		for(int i=0; i<getWidth(); i++)
+		{
+			int byte = i / 8;
+			int bit = i % 8;	
+			colors[i] = ((temp[byte] << bit) & 0x80) ? 0xFFFFFF : 0x000000;
+		}
+		delete [] temp;
+	}
+	if(closefile)
+	{
+		close();
+	}
+	return colors;
+}
+
+int *BitmapFile::getRowBW(int row, bool closefile)
+{
+	open();
+	int *colors = new int[getWidth()];
+	int index = getOffset() + m_rowsize*row;
+	fseek(m_pFile, index, SEEK_SET);
+	if(getColorDepth() == 24)
+	{
+		for(int i=0; i<getWidth(); i++)
+		{
+			char temp[3];
+			fread(temp,sizeof(char),3,m_pFile);
+			int average = (temp[0]+temp[1]+temp[2])/3;
+			colors[i] = average>128 ? 0xFFFFFF : 0x000000;
+		}
+	}
+	else if(getColorDepth() == 1)
+	{
+		delete [] colors;
+		colors = getRow(row, closefile);
+	}
+	if(closefile)
+	{
+		close();
+	}
+	return colors;
+}
+
+char *BitmapFile::getRowBitstream(int row, bool closefile)
+{
+	open();
+	int bitsperrow = (getWidth()+7)/8;
+	char *data = new char[bitsperrow];
+	for(int i = 0; i<bitsperrow; i++)
+	{
+		data[i] = 0;
+	}
+	int index = getOffset() + m_rowsize*row;
+	fseek(m_pFile, index, SEEK_SET);
+	
+	if(getColorDepth() == 24)
+	{
+		for(int i=0; i<getWidth(); i++)
+		{
+			char temp[3];
+			fread(temp,sizeof(char),3,m_pFile);
+			int average = (temp[0]+temp[1]+temp[2])/3;
+			int val = average<128?0:1;
+			data[i/8] |= (val*0x80) >> (i%8);
+		}
+	}
+	else if(getColorDepth() == 1)
+	{
+		fread(data,sizeof(char),bitsperrow,m_pFile);
+	}
+	
+	if(closefile)
+	{
+		close();
+	}
+	return data;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BitmapFile.h	Tue Nov 10 21:28:51 2015 +0000
@@ -0,0 +1,158 @@
+/**********************************************************/
+/*BitmapFile.h                                            */
+/**********************************************************/
+
+#include "mbed.h"
+
+/* Class: BitmapFile
+ * A parser for bitmap files.
+*/
+class BitmapFile
+{
+private:
+	FILE			*m_pFile;
+	char			*m_fileName;
+	int				m_rowsize;
+	
+	enum headerType {	BITMAPCOREHEADER = 12,
+						BITMAPCOREHEADER2 = 64,
+						BITMAPINFOHEADER = 40,
+						BITMAPV4HEADER = 108,
+						BITMAPV5HEADER = 124};
+						
+	enum compressType {	BI_RGB,
+						BI_RLE8,
+						BI_RLE4,
+						BI_BITFIELDS,
+						BI_JPEG,
+						BI_PNG};
+
+	/* Struct: BMPHeader
+	*
+	* The BMP header of the bitmap is read into this.	
+	*
+	* b - the first byte of the header. Should equal 'B'.
+	* m - the second byte of the header. Should equal 'M'.
+	* filesize - the size of the whole file, in bytes.
+	* reserved 1 and 2 - data specific to the applicaton which created the bitmap.
+	* offset - the offset at which the actual bitmap begins
+	*/
+							
+	__packed struct
+	{
+		char	b:8;
+		char	m:8;
+		int		filesize:32;
+		int		reserved1:16;
+		int		reserved2:16;
+		int		offset:32;
+		
+	} BMPHeader;
+	
+	
+	/* Struct: DIBHeader
+	*
+	* The DIB header of the bitmap is read into this.	
+	*
+	* headerlength - the length of the header. Should equal 40.
+	* height - the height of the bitmap.
+	* width - the width of the bitmap.
+	* cplanes - the number of color planes. Should equal 1.
+	* colordepth - the number of bits per pixel.
+	* compression - the compression method used.
+	* datasize - the size of the bitmap data, in bytes.
+	*/
+
+	int		m_headerlength;
+	__packed struct
+	{
+		int		width:32;
+		int		height:32;
+		int		cplanes:16;
+		int		colordepth:16;
+		int		compression:32;
+		int		datasize:32;
+		int		hres:32;
+		int		vres:32;
+		int		numpalettecolors:32;
+		int		importantcolors:32;		
+	} DIBHeader;
+	
+						
+public:
+	/* Constructor: BitmapFile
+	* Create the BitmapFile class, and call <Initialize>
+	*
+	* Parameters:
+	*  fname - The path of the file to open.
+	*/
+	BitmapFile(char* fname);
+	~BitmapFile();
+
+	/* Function: Initialize
+	* Parses the headers of the bitmap.
+	*
+	* Returns:
+	*  Whether the bitmap is valid.
+	*/
+	bool	Initialize();	//parses the header
+
+	/* Function: open
+	* Opens the bitmap for reading, if not already open.
+	*/
+	void	open();
+
+	/* Function: close
+	* Closes the bitmap.
+	*/
+	void	close();
+
+	/***BMP Header gets begin***/
+	int		getFileSize();
+	int		getReserved1();
+	int		getReserved2();
+	int		getOffset();
+	
+	/***DIB Header gets begin***/
+	int		getHeaderType();
+	int		getHeight();
+	int		getWidth();
+	int		getCPlanes();
+	int		getColorDepth();
+	int		getCompression();
+	int		getDataSize();
+	int		getHRes();
+	int		getVRes();
+	int		getNumPaletteColors();
+	int		getImportantColors();
+	/****DIB Header gets end****/
+	
+	/******Data gets begin******/
+	/* Function: getPixel
+	* Gets the color of a pixel
+	*
+	* Parameters:
+	*  x - The x coordinate of the pixel.
+	*  y - The y coordinate of the pixel.
+	*  closefile - if specified, close the file after reading
+	*
+	* Returns:
+	*  the color of the pixel, in hexadecimal.
+	*/
+	int		getPixel(int x, int y, bool closefile = true);
+	/* Function: getRow
+	* Gets the colors of a row
+	*
+	* Parameters:
+	*  row - The number of the row..
+	*  closefile - if specified, close the file after reading
+	*
+	* Returns:
+	*  An array of the colors of the pixels, in hexadecimal.
+	*/
+	int		*getRow(int row, bool closefile = true);
+	int		*getRowBW(int row, bool closefile = true);
+	char	*getRowBitstream(int row, bool closefile = true);
+	/*******Data gets end*******/
+	int		getRowSize();
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NeoStrip.lib	Tue Nov 10 21:28:51 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/aswild/code/NeoStrip/#f531a2be180d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PinDetect.lib	Tue Nov 10 21:28:51 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/AjK/code/PinDetect/#cb3afc45028b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Nov 10 21:28:51 2015 +0000
@@ -0,0 +1,251 @@
+#include "mbed.h"
+#include "BitmapFile.h"
+#include <string>
+#include "PinDetect.h"
+#include "NeoStrip.h"
+
+# define MAX_FILE 30
+
+#define N 32
+NeoStrip strip(p5, N);
+float bright = 0.2; // 20% is plenty for indoor use
+
+PinDetect b1(p25, PullUp);
+PinDetect b2(p29, PullUp);
+PinDetect b3(p22, PullUp);
+PinDetect b4(p27, PullUp);
+
+LocalFileSystem local("local");               // Create the local filesystem under the name "local"
+Serial pc(USBTX, USBRX); // tx, rx
+BitmapFile *MyBitmap;
+
+char *f_list[MAX_FILE];
+int file_index = 0; // get the index of file being displayed
+unsigned max_file = 0; // register how many files there are
+
+char * get_file_name() {
+    char *fn = NULL;
+    unsigned i = 0; // index in the file list;
+    DIR *d = opendir("/local");               // Opens the root directory of the local file system
+    struct dirent *p;
+    while((p = readdir(d)) != NULL) {         // Print the names of the files in the local file system
+        int l = strlen(p->d_name);
+        if (strcmp(&(p->d_name[l-3]), "BMP") == 0) {
+            i++;
+            if (file_index == i) {
+                fn = (char *) malloc(50);
+                strcpy(fn, p->d_name);
+                break;
+            }
+        }
+    }
+    closedir(d);
+
+    return fn;
+}
+
+void strip_off() {
+    for (int i=0; i<N; i++) {
+        strip.setPixel(i, 0);
+    }
+    strip.write();
+}
+
+void display_number(float f) {
+    for (int i=0; i<N; i++) {
+        if (i<(f*N))
+            strip.setPixel(i, 0xffffff);
+    }
+    strip.write();
+    wait(0.2);
+    strip_off();
+}
+
+void brightnessUp(void) {
+    if (bright < 1)
+    {
+        bright += 0.01;
+        if (bright > 1)
+            bright = 1;
+        printf("increase brightness\r\n");
+        strip.setBrightness(bright);
+        display_number(bright);
+    }
+}
+
+void brightnessDown(void) {
+    if (bright > 0)
+    {
+        bright -= 0.01;
+        if (bright < 0)
+            bright = 0;
+        printf("decrease brightness\r\n");
+        strip.setBrightness(bright);
+        display_number(bright);
+    }
+}
+
+void fileDown(void) {
+    file_index--;
+    if (file_index < 0)
+        file_index = max_file;
+    printf("fileDown to %i:%s\r\n", file_index, f_list[file_index]);
+    display_number(file_index/float(N));
+}
+
+void fileUp(void) {
+    file_index++;
+    if (file_index > max_file)
+        file_index = 0;
+    printf("fileUp to %i:%s\r\n", file_index, f_list[file_index]);
+    display_number(file_index/float(N));
+}
+
+
+// Converts HSV to RGB with the given hue, assuming
+// maximum saturation and value
+int hueToRGB(float h)
+{
+    // lots of floating point magic from the internet and scratching my head
+    float r, g, b;
+    if (h > 360)
+        h -= 360;
+    if (h < 0)
+        h += 360;
+    int i = (int)(h / 60.0);
+    float f = (h / 60.0) - i;
+    float q = 1 - f;
+    
+    switch (i % 6)
+    {
+        case 0: r = 1; g = f; b = 0; break;
+        case 1: r = q; g = 1; b = 0; break;
+        case 2: r = 0; g = 1; b = f; break;
+        case 3: r = 0; g = q; b = 1; break;
+        case 4: r = f; g = 0; b = 1; break;
+        case 5: r = 1; g = 0; b = q; break;
+        default: r = 0; g = 0; b = 0; break;
+    }
+    
+    // scale to integers and return the packed value
+    uint8_t R = (uint8_t)(r * 255);
+    uint8_t G = (uint8_t)(g * 255);
+    uint8_t B = (uint8_t)(b * 255);
+
+    return (R << 16) | (G << 8) | B;
+}
+
+
+void pattern1()
+{
+    static float dh = 360.0 / N;
+    static float x = 0;
+    printf("%f\r\n",x);
+
+    for (int i = 0; i < N; i++) {
+        int c = hueToRGB((dh * i) - x);
+        //printf("R %i, G %i, B %i\r\n", (c>>16)&0xff, (c>>8)&0xff, c&0xff);
+        strip.setPixel(i, c);
+    }
+    
+    x += 1;
+    if (x > 360)
+        x = 0;
+}
+
+
+void patternStart(void) {    
+    printf("file_index: %i\r\n", file_index);
+    if (file_index == 0) {
+        for ( int j=0; j<100; j++ ){
+            pattern1();
+            strip.write();
+            wait_ms(20);
+        }
+        return;
+    }
+    
+    printf("fn: %s\r\n", f_list[file_index]);
+    
+    char *fn = get_file_name();
+    
+    unsigned l = strlen(fn);
+    char *path = (char *) malloc(l+7);
+    path[0] = 0;
+    strcat(path, "/local/");
+    strcat(path, fn);
+    printf("path: %s\r\n", path);
+    
+    MyBitmap = new BitmapFile(path);
+    for(int row = 0; row < MyBitmap->getHeight(); row++)
+    {
+        int *row_color = MyBitmap->getRow(row, false);
+        for(int col = 0; col < MyBitmap->getWidth(); col++)
+        {
+            unsigned c = row_color[col] & 0xffffff;
+            strip.setPixel(col, c);
+            if ( c > 0xfff )
+                printf(" ");
+            else
+                printf("*");
+        }
+        strip.write();
+        wait_ms(20);
+        printf("\r\n");
+        delete [] row_color;
+    }
+    printf("closing\r\n");
+    MyBitmap->close();
+    printf("closed\r\n");
+    free(fn);
+    free(path);
+    strip_off();
+}
+
+
+
+
+int main() {
+    b1.setAssertValue( 0 );
+    b2.setAssertValue( 0 );
+    b3.setAssertValue( 0 );
+    b4.setAssertValue( 0 );
+    
+    b1.attach_asserted( &brightnessDown );
+    b2.attach_asserted( &patternStart );
+    b3.attach_asserted( &brightnessUp );
+    
+    b1.attach_asserted_held( &fileDown );
+    b3.attach_asserted_held( &fileUp );
+
+    strip.setBrightness(bright);    // set default brightness
+
+    
+    // build a list of files
+    for (unsigned i=0; i<MAX_FILE; i++)
+        f_list[i] = NULL;
+
+    unsigned i = 0; // index in the file list;
+    DIR *d = opendir("/local");               // Opens the root directory of the local file system
+    struct dirent *p;
+    while((p = readdir(d)) != NULL) {         // Print the names of the files in the local file system
+        int l = strlen(p->d_name);
+        if (strcmp(&(p->d_name[l-3]), "BMP") == 0) {
+            char *tmp_str = (char *) malloc(l+1);
+            strcpy(tmp_str, p->d_name);
+            i++;
+            f_list[i] = tmp_str;
+            printf("f_list: %i:%s\r\n", i, tmp_str);
+        }
+    }
+    closedir(d);
+    
+    max_file = i;
+    b1.setSampleFrequency();
+    b2.setSampleFrequency();
+    b3.setSampleFrequency();
+    b4.setSampleFrequency();
+    
+    while(1)
+        __WFI();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Nov 10 21:28:51 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7cff1c4259d7
\ No newline at end of file