Source code for the Curilights Controller. See http://www.saccade.com/writing/projects/CuriController/ for details.
Dependencies: FatFileSystem mbed
This is the source code for the Curilights controller. This lets you interactively control a string of Curilights. It provides a simple click-wheel user interface for changing colors, brightness and behavior. It responds to movement and lighting.
Finished Controller
System Block Diagram
NokiaLCD.cpp
- Committer:
- isonno
- Date:
- 2012-01-16
- Revision:
- 2:965388eecf95
- Parent:
- 0:6da5625a6946
File content as of revision 2:965388eecf95:
/* NokiaLCD.cpp - Library for a Nokia LCD with the epson driver. Created by Thomas Jespersen, July 2009 (Originally Arduino Sketch by Gravitech.us) Released into the public domain. Reworked by J. P------- for the TI LM3S9B96 Reworked again by J. P------- for the mbed */ #include "NokiaLCD.h" // Define Software SPI Pin Signal // Epson S1D15G10 Command Set #define DISON 0xaf #define DISOFF 0xae #define DISNOR 0xa6 #define DISINV 0xa7 #define COMSCN 0xbb #define DISCTL 0xca #define SLPIN 0x95 #define SLPOUT 0x94 #define PASET 0x75 #define CASET 0x15 #define DATCTL 0xbc #define RGBSET8 0xce #define RAMWR 0x5c #define RAMRD 0x5d #define PTLIN 0xa8 #define PTLOUT 0xa9 #define RMWIN 0xe0 #define RMWOUT 0xee #define ASCSET 0xaa #define SCSTART 0xab #define OSCON 0xd1 #define OSCOFF 0xd2 #define PWRCTR 0x20 #define VOLCTR 0x81 #define VOLUP 0xd6 #define VOLDOWN 0xd7 #define TMPGRD 0x82 #define EPCTIN 0xcd #define EPCOUT 0xcc #define EPMWR 0xfc #define EPMRD 0xfd #define EPSRRD1 0x7c #define EPSRRD2 0x7d #define NOP 0x25 #include "SmallText.h" #include "Splash.h" #include "ColorWheel.h" #include "NumSprites.h" #include "f18TextData.h" const sprite_data_t * NumSprites[] = {&N0_sprt, &N1_sprt, &N2_sprt, &N3_sprt, &N4_sprt, &N5_sprt, &N6_sprt, &N7_sprt, &N8_sprt, &N9_sprt }; CheapLCD::CheapLCD( PinName mosi, PinName sclk, PinName cs, PinName rst ) :fSPI( mosi, NC, sclk ), fReset( rst ), fCS( cs ), fCSLevel( 0 ), fBacklight( p21 ) { init(); } void CheapLCD::init() { // Initialize the LCD display // Hardware Reset LCD fCS = 1; fReset = 0; fSPI.format( 9 ); fSPI.frequency( 5000000 ); wait_ms( 1 ); fReset = 1; wait_ms( 1 ); fCS = 0; // Display control sendCMD(DISCTL); sendData(0x0C); // 2 divisions, Field swithcing period sendData(32); // 132 lines to be display sendData(0); // Inversely hightlighted lines - 1 sendData(0); sendCMD(COMSCN); // comscn sendData(0x00); sendCMD(OSCON); // oscon sendCMD(SLPOUT); // sleep out sendCMD(PWRCTR); // power ctrl sendData(0x0f); // everything on, no external reference resistors wait_ms( 1 ); sendCMD(VOLCTR); // electronic volume, this is kinda contrast/brightness sendData(0x24); // this might be different for individual LCDs sendData(0x03); // sendCMD(DISINV); // display mode sendCMD(DATCTL); // datctl sendData(0x02); // Set sendData(0); // RGB (not BGR) LCD sendData(0x02); // 16 bit grayscale type A sendCMD(DISON); // display on fCS = 1; } void CheapLCD::sendCMD( byte data ) { fSPI.write( data & 0xFF ); } void CheapLCD::sendData( byte data ) { fSPI.write( data | 0x100 ); } // Chip select must be asserted low while talking to the display. // We use this class to keep track of nested calls, so it's done // once per operation. class ChipSelect { public: ChipSelect( CheapLCD * lcd ): fLCD( lcd ) { if (fLCD->fCSLevel == 0) fLCD->fCS = 0; fLCD->fCSLevel++; } ~ChipSelect() { fLCD->fCSLevel--; if (fLCD->fCSLevel < 0) printf("WTF?? fLCD level negative\r\n"); if (fLCD->fCSLevel == 0) fLCD->fCS = 1; } private: CheapLCD * fLCD; }; /**************************************/ /* Put pixel to LCD */ /**************************************/ void CheapLCD::put_pixel(byte color, byte x, byte y) { ChipSelect cs(this); sendCMD(CASET); // page start/end ram sendData(x); // for some reason starts at 2 sendData(x+1); sendCMD(PASET); // column start/end ram sendData(y); sendData(y+1); sendCMD(RAMWR); sendData(color); } void CheapLCD::set_box(byte x1, byte y1, byte x2, byte y2) { ChipSelect cs(this); /* sendCMD(CASET); // page start/end ram sendData(x1); // for some reason starts at 2 sendData(x2); sendCMD(PASET); // column start/end ram sendData(y1); sendData(y2); */ sendCMD(CASET); // page start/end ram sendData(131-x2); // for some reason starts at 2 sendData(131-x1); sendCMD(PASET); // column start/end ram sendData(131-y2); sendData(131-y1); } #define MEMPIXEL(color) sendData( (color>>4) & 0x00FF);\ sendData( ((color & 0x0F) << 4) | (color >> 8));\ sendData( color & 0xFF ); void CheapLCD::clear(uint32_t color, byte x1, byte y1, byte x2, byte y2) { ChipSelect cs(this); uint32_t i; uint32_t total_bytes1; uint32_t total_bytes2; uint32_t total_bytes; CheapLCD::set_box(x1, y1, x2, y2); sendCMD(RAMWR); total_bytes1 = (x2 - x1) +1; total_bytes2 = (y2 - y1) +1; total_bytes = total_bytes1 * total_bytes2; for (i = 0; i < total_bytes/2; i++) { MEMPIXEL( color ) } } void CheapLCD::copy_screen( const image_data_t * screenData ) { ChipSelect cs(this); int i, start, row, num; // clear( BLACK, 0, 0, 131, 131 ); sendCMD(CASET); // page start/end ram sendData(0); // for some reason starts at 2 sendData(131); sendCMD(PASET); // column start/end ram sendData(0); sendData(131); sendCMD(RAMWR); for (row = 0; row <= 131; ++row) { start = (((row + 2) % 131)) * (132/2)*3; // start = row * (132/2)*3; num = (132/2)*3; for (i = 0; i < num; ++i) sendData( screenData->pixel_data[start + i] ); } } /* // NOTE! (x1-x0)+1 must be even! void CheapLCD::copy_screen_section( byte x0, byte y0, byte x1, byte y1, const image_data_t * screenData ) { int row, i, num, start; // set_box( x0, y0, x1, y1 ); sendCMD(CASET); // page start/end ram sendData((131-x1)); sendData((131-x0)); sendCMD(PASET); // column start/end ram if (y0 == 0) sendData(2); else sendData(y0); y1++; sendData(y1); sendCMD(RAMWR); for (row = y0; row <= y1; ++row) { if (y0 == 0) start = (((row + 2) % y1)) * (132/2)*3; else start = (row) * (132/2)*3; start += (x0/2) * 3; num = ((x1 - x0)+1)/2 * 3; for (i = 0; i < num; ++i) sendData( screenData->pixel_data[start + i] ); } } */ void CheapLCD::splash(int demo) { switch (demo) { case 1: copy_screen( &ColorWheel_img ); break; /* */ default: case 0: copy_screen( &Splash_img ); break; } } void CheapLCD::ramp( uint32_t color, uint32_t y, uint32_t height ) { ChipSelect cs(this); int i, j; uint32_t red = (color >> 8); uint32_t grn = (color & 0xFF) >> 4; uint32_t blu = (color & 0x0F); uint32_t c = color, scanline[132/2]; for (i = 0; i < 132/2; ++i) { if (((i+1) % 4) == 0) { if (red > 0) red--; if (grn > 0) grn--; if (blu > 0) blu--; c = (red << 8) | (grn << 4) | blu; } scanline[i] = c; } set_box( 0, y, 131, y+height ); sendCMD(RAMWR); for (i = 0; i < height; ++i) { for (j = 0; j < 132/2; ++j) { c = scanline[j]; MEMPIXEL( c ); } } } void CheapLCD::draw_color_bar() { ChipSelect cs(this); clear(RED,0,0,131,33); clear(GREEN,0,34,131,66); clear(BLUE,0,67,131,99); clear(WHITE,0,100,131,131); ramp( RED, 0, 15 ); ramp( GREEN, 34, 15 ); ramp( BLUE, 67, 15 ); ramp( WHITE, 100, 15 ); } void CheapLCD::erase() { clear( BLACK, 0, 0, 131, 131 ); } void CheapLCD::send_packed_pixels( uint32_t pixel_data[], unsigned int numPixels ) { ChipSelect cs(this); uint32_t c0, c1; unsigned char d; unsigned int i; sendCMD(RAMWR); for (i = 0; i < numPixels/2; ++i) { c0 = pixel_data[i*2]; c1 = pixel_data[i*2+1]; d = (c0 >> 4) | ((c0 >> 4) & 0xF); sendData( d ); d = ((c0 & 0xF) << 4) | (c1 >> 8); sendData( d ); d = c1 & 0xFF; sendData( d ); } } void CheapLCD::draw_text_line(uint32_t fcolor, uint32_t bcolor,byte x, byte y,char c) { ChipSelect cs(this); unsigned int i; uint32_t text_pixels[8]; set_box(x,y,x,y+7); for(i=0;i<8;i++) { if ((1<<(7-i)) & c) text_pixels[i] = fcolor; else text_pixels[i] = bcolor; } send_packed_pixels( text_pixels, 8 ); } void unpack_color( short * r, short * g, short * b, uint32_t color ) { *r = color>>8; *g = (color>>4) & 0x0F; *b = color & 0x0F; } void CheapLCD::draw_mask( uint32_t fcolor, uint32_t bcolor, byte x, byte y, uint32_t numRows, uint32_t numCols, const unsigned char * pixel_data ) { ChipSelect cs(this); uint32_t sline[132]; // Worse case scanline buffer short rf = 0, gf = 0, bf = 0, rb, gb, bb, spixel; short r, g, b; int row, col, ypos; unpack_color( &rf, &gf, &bf, fcolor ); unpack_color( &rb, &gb, &bb, bcolor ); // Whacky epson driver chip: The width of the line must // be odd, and the first and last pixels are tossed when // filling the display // uint32_t oddNumCols = (numCols & 1) ? numCols : numCols + 1; sline[0] = bcolor; for (row = 0; row < numRows; row++) { for (col = 0; col < numCols; col++) { spixel = pixel_data[row * (numCols/2 + (numCols & 1)) + col/2]; spixel = (col & 1) ? spixel & 0x0F : (spixel >> 4); // Note f*t + b*(1-t) reduces to t*(f-b) + b r = ((spixel * (rf - rb)) >> 4) + rb; g = ((spixel * (gf - gb)) >> 4) + gb; b = ((spixel * (bf - bb)) >> 4) + bb; sline[col+1] = (uint32_t) ( (r << 8) | (g << 4) | b ); } sline[col+1] = bcolor; ypos = (y + numRows-1) - row; set_box( x, ypos, x + numCols-1, ypos ); send_packed_pixels( sline, numCols+2 ); } } void CheapLCD::draw_glyph_text( uint32_t fcolor, uint32_t bcolor, int x, int y, const char * str ) { const char * p = str; int xpos = x; while (*p) { if (*p == ' ') xpos += 8; else { const glyph_data_t * g = f18_glyph_array[((*p) & 0x7f) - 0x21]; draw_glyph( fcolor, bcolor, xpos, y, g ); xpos += (g->numCols + 1); } p++; } } // Note "y" in this case refers to the baseline origin, not top left void CheapLCD::draw_glyph( uint32_t fcolor, uint32_t bcolor, byte x, byte y, const glyph_data_t * glyph ) { int y1 = (int)y - (int)(glyph->numRows) + glyph->baseline; draw_mask( fcolor, bcolor, x, (byte) y1, glyph->numRows, glyph->numCols, glyph->pixel_data ); } void CheapLCD::draw_sprite( uint32_t fcolor, uint32_t bcolor, byte x, byte y, const sprite_data_t * sprite ) { draw_mask( fcolor, bcolor, x, y, sprite->numRows, sprite->numCols, sprite->pixel_data ); } void CheapLCD::draw_number( uint32_t fcolor, uint32_t bcolor, byte x, byte y, int number ) { ChipSelect cs( this ); char digits[10]; int i, numDigits = 0; const sprite_data_t * sprite; // Store digits sprintf( digits, "%d", number ); numDigits = strlen( digits ); for (i = 0; i < numDigits; ++i) { sprite = NULL; switch (digits[i]) { case '-': sprite = &minus_sprt; break; default: if ((digits[i] >= '0') && (digits[i] <= '9')) sprite = NumSprites[digits[i] - '0']; break; } if (sprite) { draw_sprite( fcolor, bcolor, x, y, sprite ); x += sprite->numCols; clear( bcolor, x, y, x, y + (sprite->numRows - 1) ); x++; } } } #define SHADE 0xB #define DKRED (SHADE << 8) #define DKGRN (SHADE << 4) #define DKBLU (SHADE) #define LABELOFF 8 #define NUMBEROFF 52 /* void CheapLCD::backlight( tBoolean backlight_on ) { if (backlight_on) BL0 else BL1; } void CheapLCD::draw_RGB( int r, int g, int b ) { ChipSelect cs( this ); clear( BLACK, 0, 0, 131, 59 ); clear( DKRED, 0, 60, 131, 83 ); clear( DKGRN, 0, 84, 131, 107 ); clear( DKBLU, 0, 108, 131, 131 ); draw_sprite( WHITE, BLACK, 6, 13, &RGBColor_sprt ); draw_sprite( WHITE, DKRED, LABELOFF, 65, &Red_sprt ); draw_sprite( WHITE, DKGRN, LABELOFF, 89, &Grn_sprt ); draw_sprite( WHITE, DKBLU, LABELOFF, 111,&Blu_sprt ); draw_number( WHITE, DKRED, NUMBEROFF, 65, r ); draw_number( WHITE, DKGRN, NUMBEROFF, 89, g ); draw_number( WHITE, DKBLU, NUMBEROFF, 112,b ); } void CheapLCD::demo_sprite( void ) { draw_sprite( WHITE, RED, 10, 10, &OddAt_sprt ); } */ void CheapLCD::demo_number( int num ) { draw_number( RED, WHITE, 10, 10, num ); } void CheapLCD::draw_text(uint32_t fcolor, uint32_t bcolor, byte x, byte y,char *text) { ChipSelect cs( this ); byte c; byte t; unsigned int i; unsigned int j; while(*text != 0) { t = *text; i = t - 32; i = i * 5; for(j = i; j < i+5; j++) { c = font[j]; draw_text_line(fcolor, bcolor, x++, y, c); } draw_text_line(fcolor, bcolor, x++, y, 0); text++; } } #define DATALINE(name, y, reg)\ draw_data_line( name, y, (int)(reg[0]), (int)(reg[1]), (int)(reg[2]), (int)(reg[3]) ); char * convert_float( const char * msg, float H ) { static char digits[15]; if (H * 1000 == 1000) sprintf( digits, "%s1.0", msg ); else if (H * 1000 > 100) sprintf( digits, "%s0.%d", msg, (int) (H * 1000) ); else if (H * 1000 > 10) sprintf( digits, "%s0.0%d", msg, (int) (H * 1000) ); else sprintf( digits, "%s0.00%d", msg, (int) (H * 1000) ); return digits; } /* void CheapLCD::draw_HSL( float H, float S, float L ) { byte x = (byte) (H * 131.0); byte y = (byte) (S * 131.0); copy_screen( &hslImage_img ); clear( WHITE, x-2, y-2, x+2, y+2 ); draw_text( WHITE, 0x0888, 10, 120, convert_float( "H=", H ) ); draw_text( WHITE, 0x0888, 65, 120, convert_float( "S=", S ) ); } */