A demo program for DOGL-128 LCD module. Based on Mike Sheldon's 3D Tie Fighter demo.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DogLCD.cpp Source File

DogLCD.cpp

00001 #include "DogLCD.h"
00002 
00003 // macro to make sure x falls into range from low to high (inclusive)
00004 #define CLAMP(x, low, high) { if ( (x) < (low) ) x = (low); if ( (x) > (high) ) x = (high); } while (0);
00005 
00006 void DogLCD::_send_commands(const unsigned char* buf, size_t size)
00007 {
00008     // for commands, A0 is low
00009     _spi.format(8,0);
00010     _spi.frequency(10000000);
00011     _cs = 0;
00012     _a0 = 0;
00013     while ( size-- > 0 )
00014         _spi.write(*buf++);
00015     _cs = 1;
00016 }
00017 
00018 void DogLCD::_send_data(const unsigned char* buf, size_t size)
00019 {
00020     // for data, A0 is high
00021     _spi.format(8,0);
00022     _spi.frequency(10000000);
00023     _cs = 0;
00024     _a0 = 1;
00025     while ( size-- > 0 )
00026         _spi.write(*buf++);
00027     _cs = 1;
00028     _a0 = 0;
00029 }
00030 
00031 // set column and page number
00032 void DogLCD::_set_xy(int x, int y)
00033 {
00034     //printf("_set_xy(%d,%d)\n", x, y);
00035     CLAMP(x, 0, LCDWIDTH-1);
00036     CLAMP(y, 0, LCDPAGES-1);
00037     unsigned char cmd[3];
00038     cmd[0] = 0xB0 | (y&0xF);
00039     cmd[1] = 0x10 | (x&0xF);
00040     cmd[2] = (x>>4)&0xF;
00041     _send_commands(cmd, 3);        
00042 }
00043 
00044 // initialize and turn on the display
00045 void DogLCD::init()
00046 {
00047     const unsigned char init_seq[] = {
00048         0x40,    //Display start line 0
00049         0xa1,    //ADC reverse
00050         0xc0,    //Normal COM0...COM63
00051         0xa6,    //Display normal
00052         0xa2,    //Set Bias 1/9 (Duty 1/65)
00053         0x2f,    //Booster, Regulator and Follower On
00054         0xf8,    //Set internal Booster to 4x
00055         0x00,
00056         0x27,    //Contrast set
00057         0x81,
00058         0x16,
00059         0xac,    //No indicator
00060         0x00,
00061         0xaf,    //Display on
00062     };        
00063     //printf("Reset=L\n");
00064     _reset = 0;
00065     //printf("Power=H\n");
00066     _power = 1;
00067     //wait_ms(1);
00068     //printf("Reset=H\n");
00069     _reset = 1;
00070     //wait(5);
00071     //printf("Sending init commands\n");
00072     _send_commands(init_seq, sizeof(init_seq));
00073 }
00074 
00075 void DogLCD::send_pic(const unsigned char* data)
00076 {
00077     //printf("Sending picture\n");
00078     for (int i=0; i<LCDPAGES; i++)
00079     {
00080         _set_xy(0, i);
00081         _send_data(data + i*LCDWIDTH, LCDWIDTH);
00082     }
00083 }
00084 
00085 void DogLCD::clear_screen()
00086 {
00087     //printf("Clear screen\n");
00088     memset(_framebuffer, 0, sizeof(_framebuffer));
00089     if ( _updating == 0 )
00090     {
00091         send_pic(_framebuffer);
00092     }
00093 }
00094 
00095 void DogLCD::all_on(bool on)
00096 {
00097     //printf("Sending all on %d\n", on);
00098     unsigned char cmd = 0xA4 | (on ? 1 : 0);
00099     _send_commands(&cmd, 1);
00100 }
00101 
00102 void DogLCD::pixel(int x, int y, int colour)
00103 {
00104     CLAMP(x, 0, LCDWIDTH-1);
00105     CLAMP(y, 0, LCDHEIGHT-1);
00106     int page = y / 8;
00107     unsigned char mask = 1<<(y%8);
00108     unsigned char *byte = &_framebuffer[page*LCDWIDTH + x];
00109     if ( colour == 0 )
00110         *byte &= ~mask; // clear pixel
00111     else
00112         *byte |= mask; // set pixel
00113     if ( !_updating )
00114     {
00115         _set_xy(x, page);
00116         _send_data(byte, 1);
00117     }
00118 }
00119 
00120 void DogLCD::fill(int x, int y, int width, int height, int colour)
00121 {
00122     /*
00123       If we need to fill partial pages at the top:
00124       
00125       ......+---+---+.....
00126        ^    | = | = |     = : don't touch
00127        |    | = | = |     * : update 
00128       y%8   | = | = |      
00129        |    | = | = |      
00130        v    | = | = |      
00131     y---->  | * | * |      
00132             | * | * |      
00133             | * | * |
00134             +---+---+      
00135     */
00136     //printf("fill(x=%d, y=%d, width=%d, height=%d, colour=%x)\n",  x, y, width, height, colour);
00137     CLAMP(x, 0, LCDWIDTH-1);
00138     CLAMP(y, 0, LCDHEIGHT-1);
00139     CLAMP(width, 0, LCDWIDTH - x);
00140     CLAMP(height, 0, LCDHEIGHT - y);
00141     int page = y/8;
00142     int firstpage = page;
00143     int partpage = y%8;
00144     if ( partpage != 0 )
00145     {
00146         // we need to process partial bytes in the top page
00147         unsigned char mask = (1<<partpage) - 1; // this mask has 1s for bits we need to leave
00148         unsigned char *bytes = &_framebuffer[page*LCDWIDTH + x];
00149         for ( int i = 0; i < width; i++, bytes++ )
00150         {
00151           // clear "our" bits
00152           *bytes &= mask;
00153           if ( colour != 0 )
00154             *bytes |= ~mask; // set our bits
00155         }
00156         height -= partpage;
00157         page++;
00158     }
00159     while ( height >= 8 )
00160     {
00161         memset(&_framebuffer[page*LCDWIDTH + x], colour == 0 ? 0 : 0xFF, width);
00162         page++;
00163         height -= 8; 
00164     } 
00165     if ( height != 0 )
00166     {
00167         // we need to process partial bytes in the bottom page
00168         unsigned char mask = ~((1<<partpage) - 1); // this mask has 1s for bits we need to leave
00169         unsigned char *bytes = &_framebuffer[page*LCDWIDTH + x];
00170         for ( int i = 0; i < width; i++, bytes++ )
00171         {
00172           // clear "our" bits
00173           *bytes &= mask;
00174           if ( colour != 0 )
00175             *bytes |= ~mask; // set our bits
00176         }
00177         page++;
00178     }
00179     //printf("_updating=%d\n", _updating);
00180     if ( !_updating )
00181     {
00182         int laststpage = page;
00183         for ( page = firstpage; page < laststpage; page++)
00184         {
00185             //printf("setting x=%d, page=%d\n", x, page);
00186             _set_xy(x, page);
00187             //printf("sending %d bytes at offset %x\n", width, page*LCDWIDTH + x);
00188             _send_data(&_framebuffer[page*LCDWIDTH + x], width);
00189         }
00190     }
00191 }     
00192 
00193 void DogLCD::beginupdate()
00194 {
00195     _updating++;
00196     //printf("beginupdate: %d\n", _updating);
00197 }
00198 
00199 void DogLCD::endupdate()
00200 {    
00201     _updating--;
00202     //printf("endupdate: %d\n", _updating);
00203     if ( _updating == 0 )
00204     {
00205         send_pic(_framebuffer);
00206     }
00207 }