Kevin Kadooka / SSD1351

Dependencies:   BurstSPI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SSD1351.cpp Source File

SSD1351.cpp

00001 #include "SSD1351.h"
00002 #include "mbed.h"
00003 #include "BurstSPI.h"
00004 
00005 const uint16_t font[] = {
00006     0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 
00007     0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xF6DE, 0xFFFE, 
00008     0x0000, 0x4904, 0xB400, 0xBEFA, 0x79E4, 0x8542, 0x5556, 0x4800, 0x5244, 0x4494, 0xABAA, 0x0BA0, 0x0028, 0x0380, 0x0024, 0x0540, 
00009     0xF6DE, 0x4924, 0xE7CE, 0xE59E, 0xB792, 0xF39E, 0xF3DE, 0xE492, 0xF7DE, 0xF792, 0x0820, 0x0828, 0x2A22, 0x1C70, 0x88A8, 0xE504, 
00010     0x57C6, 0x57DA, 0xD75C, 0x7246, 0xD6DC, 0xF3CE, 0xF3C8, 0x73D6, 0xB7DA, 0xE92E, 0x24D4, 0xB75A, 0x924E, 0xBEDA, 0xBFFA, 0x56D4, 
00011     0xD748, 0x56F6, 0xD76A, 0x711C, 0xE924, 0xB6D6, 0xB6A4, 0xB7FA, 0xB55A, 0xB524, 0xE54E, 0xF24E, 0x1110, 0xE49E, 0x5400, 0x000E, 
00012     0x8800, 0x01DE, 0x935C, 0x01C6, 0x25D6, 0x0EE6, 0x2BA4, 0x0F9C, 0x935A, 0x4124, 0x209C, 0x92EA, 0xC92E, 0x03FA, 0x035A, 0x0154, 
00013     0x0AE8, 0x0AB2, 0x13C8, 0x0F3C, 0x5D24, 0x02D6, 0x02F4, 0x02FE, 0x02AA, 0x159C, 0x1DEE, 0x6A26, 0x4824, 0x6A26, 0x7800, 0xFFFE
00014 };
00015 
00016 //Constructors
00017 SSD1351::SSD1351(PinName mosi_pin, PinName sclk_pin, PinName dc_pin, PinName cs_pin, PinName rst_pin)
00018     :cs(cs_pin), dc(dc_pin), rst(rst_pin), spi(mosi_pin, NC, sclk_pin)
00019 {
00020     begin();
00021 }
00022 SSD1351::SSD1351()
00023     :cs(OLED_CS), dc(OLED_DC), rst(OLED_RST), spi(OLED_MOSI, NC, OLED_SCLK)
00024 {
00025     begin();
00026 }
00027 
00028 //Set the buffer pointer
00029 void SSD1351::setBuf(uint8_t* _buf){
00030     buf = _buf;
00031 }
00032 
00033 //Set collision mask pointer
00034 void SSD1351::setCMask(uint8_t* _cmask){
00035     collisionmask = _cmask;
00036 }
00037 
00038 //Basic SPI write command
00039 void SSD1351::spiwrite(uint8_t c){
00040     spi.fastWrite(c);
00041 }
00042 
00043 //Write a command to OLED
00044 void SSD1351::writeCommand(uint8_t c){
00045     dc = 0;
00046     cs = 0;
00047     spiwrite(c);
00048     wait_us(1); //We need the delay during the init sequence - I don't know why
00049     cs = 1;
00050 }
00051 
00052 //Write delay to OLED
00053 void SSD1351::writeData(uint8_t c){
00054     dc = 1;
00055     cs = 0;
00056     spiwrite(c);
00057     wait_us(1);
00058     cs = 1;
00059 }
00060 
00061 //Initialize the SSD1351
00062 void SSD1351::begin(){
00063     spi.format(8,3);
00064     spi.frequency(20000000);
00065     
00066     cs = 0;
00067     
00068     rst = 1;
00069     //SSD1351 datasheet says low pulse width for reset = 2 us, MINIMUM
00070     wait_ms(5);
00071     rst = 0;
00072     wait_ms(5);
00073     rst = 1;
00074     wait_ms(5);
00075     
00076     writeCommand(SSD1351_CMD_COMMANDLOCK);  // set command lock
00077     writeData(0x12);  
00078     writeCommand(SSD1351_CMD_COMMANDLOCK);  // set command lock
00079     writeData(0xB1);
00080 
00081     writeCommand(SSD1351_CMD_DISPLAYOFF);       // 0xAE
00082 
00083     writeCommand(SSD1351_CMD_CLOCKDIV);         // 0xB3
00084     writeCommand(0xF1);                         // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
00085     
00086     writeCommand(SSD1351_CMD_MUXRATIO);
00087     writeData(127);
00088     
00089     writeCommand(SSD1351_CMD_SETREMAP);
00090     //writeData(0x74);
00091     writeData(0x66);
00092   
00093     writeCommand(SSD1351_CMD_SETCOLUMN);
00094     writeData(0x00);
00095     writeData(0x7F);
00096     writeCommand(SSD1351_CMD_SETROW);
00097     writeData(0x00);
00098     writeData(0x7F);
00099 
00100     writeCommand(SSD1351_CMD_STARTLINE);        // 0xA1
00101     writeData(0);
00102 
00103     writeCommand(SSD1351_CMD_DISPLAYOFFSET);    // 0xA2
00104     writeData(0x0);
00105 
00106     writeCommand(SSD1351_CMD_SETGPIO);
00107     writeData(0x00);
00108     
00109     writeCommand(SSD1351_CMD_FUNCTIONSELECT);
00110     writeData(0x01); // internal (diode drop)
00111     //writeData(0x01); // external bias
00112 
00113     //writeCommand(SSSD1351_CMD_SETPHASELENGTH);
00114     //writeData(0x32);
00115 
00116     writeCommand(SSD1351_CMD_PRECHARGE);
00117     writeCommand(0x32);
00118  
00119     writeCommand(SSD1351_CMD_VCOMH);
00120     writeCommand(0x05);
00121 
00122     writeCommand(SSD1351_CMD_NORMALDISPLAY);
00123 
00124     writeCommand(SSD1351_CMD_CONTRASTABC);
00125     writeData(0xC8);
00126     writeData(0x80);
00127     writeData(0xC8);
00128 
00129     writeCommand(SSD1351_CMD_CONTRASTMASTER);
00130     writeData(0x0F);
00131 
00132     writeCommand(SSD1351_CMD_SETVSL );
00133     writeData(0xA0);
00134     writeData(0xB5);
00135     writeData(0x55);
00136     
00137     writeCommand(SSD1351_CMD_PRECHARGE2);
00138     writeData(0x01);
00139     
00140     writeCommand(SSD1351_CMD_DISPLAYON);
00141 }
00142 
00143 /*
00144 //Fill a rectangular area
00145 void SSD1351::fillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t fillcolor){
00146     writeCommand(SSD1351_CMD_SETCOLUMN);
00147     writeData(x);
00148     writeData(x+w-1);
00149     writeCommand(SSD1351_CMD_SETROW);
00150     writeData(y);
00151     writeData(y+h-1);
00152     writeCommand(SSD1351_CMD_WRITERAM);
00153     dc = 1;
00154     cs = 0;
00155     
00156     for(uint16_t i=0; i < w*h; i++){
00157         spiwrite(fillcolor >> 8);
00158         spiwrite(fillcolor);
00159     }
00160 }
00161 */
00162 
00163 //Enable writing to the SSD1351 RAM
00164 void SSD1351::enableWrite(){
00165     cs = 0;
00166     writeCommand(SSD1351_CMD_SETCOLUMN);
00167     writeData(0);
00168     writeData(127);
00169     writeCommand(SSD1351_CMD_SETROW);
00170     writeData(0);
00171     writeData(127);
00172     writeCommand(SSD1351_CMD_WRITERAM);
00173     dc = 1;
00174     cs = 0;
00175 }
00176 
00177 //Fill the buffer with a solid color
00178 void SSD1351::fillBuf(uint16_t fillcolor){
00179     for(uint16_t i=0; i < 128*128; i++){
00180         buf[2*i] = fillcolor >> 8;
00181         buf[2*i+1] = fillcolor;
00182     }
00183 }
00184 
00185 //Write the buffer to OLED RAM
00186 void SSD1351::writeBuf(){
00187     for(uint16_t i=0; i < 32768; i++){
00188         spiwrite(buf[i]);
00189     }
00190 }
00191 
00192 //Draw a filled rectangle
00193 void SSD1351::fillRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color){
00194     int16_t start = y*256 + x*2;
00195     uint16_t xs = 0;
00196     uint16_t xe = 0;
00197     uint16_t ys = 0;
00198     uint16_t ye = 0;
00199     
00200     if(x < 0){
00201         xs = -x;
00202     }
00203     if(y < 0){
00204         ys = -y;
00205     }
00206     if(x+w > 127){
00207         xe = x+w-128;
00208     }
00209     if(y+h > 127){
00210         ye = y+h-128;
00211     }
00212     
00213     for(uint16_t j=0+ys; j<h-ye; j++){
00214         for(uint16_t i=0+xs; i<w-xe; i++){
00215             buf[start +j*256 + i*2] = color >> 8;
00216             buf[start +j*256 + i*2 +1] = color;
00217         }
00218     }
00219 }
00220 
00221 //Draw an open rectangle
00222 void SSD1351::openRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color){
00223     int16_t start = y*256 + x*2;
00224     uint16_t xs = 0;
00225     uint16_t xe = 0;
00226     uint16_t ys = 0;
00227     uint16_t ye = 0;
00228     
00229     if(x < 0){
00230         xs = -x;
00231     }
00232     if(y < 0){
00233         ys = -y;
00234     }
00235     if(x+w > 127){
00236         xe = x+w-128;
00237     }
00238     if(y+h > 127){
00239         ye = y+h-128;
00240     }
00241     
00242     for(uint16_t j=ys; j<h-ye; j++){
00243         for(uint16_t i=xs; i<w-xe; i++){
00244             if((j == ys & ys == 0) | (j == h-ye-1 & ye == 0) | (i == xs & xs == 0) |  (i == w-xe-1 & xe == 0)){
00245                 buf[start +j*256 + i*2] = color >> 8;
00246                 buf[start +j*256 + i*2 +1] = color;
00247             }
00248         }
00249     }
00250 }
00251 
00252 void SSD1351::drawHLine(int16_t x, int16_t y, int16_t length, uint16_t color){
00253     if(y < 0 | y > 127){return;}
00254     
00255     int32_t start = y*256 + x*2;
00256     uint16_t xs = 0;
00257     uint16_t xe = 0;
00258     int8_t sign;
00259     
00260     if(length > 0){
00261         sign = 1;
00262     }
00263     else{
00264         sign = -1;
00265     }
00266     
00267     if(x < 0){
00268         xs = -x;
00269     }
00270     else if(x > 127){
00271         xs = x-127;
00272     }
00273     if(x+length < 0){
00274         xe = -(x+length);
00275     }
00276     else if(x+length > 127){
00277         xe = x+length-127;
00278     }
00279     
00280     for(int16_t i=xs; i<abs(length)-xe; i++){
00281         buf[start + sign*i*2] = color >> 8;
00282         buf[start + sign*i*2 + 1] = color;
00283     }
00284 }
00285 
00286 void SSD1351::drawVLine(int16_t x, int16_t y, int16_t length, uint16_t color){
00287     if(x < 0 | x > 127){return;}
00288     
00289     int32_t start = y*256 + x*2;
00290     uint16_t ys = 0;
00291     uint16_t ye = 0;
00292     int8_t sign;
00293     
00294     if(length > 0){
00295         sign = 1;
00296     }
00297     else{
00298         sign = -1;
00299     }
00300     
00301     if(y < 0){
00302         ys = -y;
00303     }
00304     else if(y > 127){
00305         ys = y-127;
00306     }
00307     if(y+length < 0){
00308         ye = -(y+length+1);
00309     }
00310     else if(y+length > 127){
00311         ye = y+length-127;
00312     }
00313     
00314     for(int16_t i=ys; i<abs(length)-ye; i++){
00315         buf[start + sign*i*256] = color >> 8;
00316         buf[start + sign*i*256 + 1] = color;
00317     };
00318 }
00319 
00320 void SSD1351::drawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color){
00321     bool steep = (abs(y2-y1) > abs(x2-x1));
00322     int16_t temp;
00323     if(steep){
00324         temp = x1;
00325         x1 = y1;
00326         y1 = temp;
00327         
00328         temp = x2;
00329         x2 = y2;
00330         y2 = temp;
00331     }
00332     if(x1 > x2){
00333         temp = x1;
00334         x1 = x2;
00335         x2 = temp;
00336         
00337         temp = y1;
00338         y1 = y2;
00339         y2 = temp;;
00340     }
00341     int16_t dx = x2-x1;
00342     int16_t dy = abs(y2-y1);
00343     float error = dx / 2.0f;
00344     int16_t ystep = (y1 < y2) ? 1 : -1;
00345     int16_t y = y1;
00346     int16_t maxX = x2;
00347     
00348     for(int16_t x = x1; x<maxX; x++){
00349         if(x >= 0 & x<128 & y >= 0 & y<128){
00350             if(steep){
00351                 buf[y*2 + x*256] = color >> 8;
00352                 buf[y*2 + x*256 + 1] = color;
00353             }
00354             else{
00355                 buf[x*2 + y*256] = color >> 8;
00356                 buf[x*2 + y*256 + 1] = color;
00357             }
00358         }
00359         error -= dy;
00360         if(error < 0)
00361         {
00362             y += ystep;
00363             error += dx;
00364         }
00365     }
00366 }
00367 
00368 void SSD1351::openCircle(int16_t x0, int16_t y0, uint16_t radius, uint16_t color){
00369     int16_t x = radius;
00370     int16_t y = 0;
00371     int16_t err = 0;
00372     
00373     while(x >= y){
00374         if(x0+x >= 0 & x0+x <128 & y0+y >= 0 & y0+y<128){
00375             buf[(x0 + x)*2 + (y0 + y)*256] = color >> 8;
00376             buf[(x0 + x)*2 + (y0 + y)*256 + 1] = color;
00377         }
00378         if(x0+y >= 0 & x0+y <128 & y0+x >= 0 & y0+x<128){
00379             buf[(x0 + y)*2 + (y0 + x)*256] = color >> 8;
00380             buf[(x0 + y)*2 + (y0 + x)*256 + 1] = color;
00381         }
00382         if(x0-y >= 0 & x0-y <128 & y0+x >= 0 & y0+x<128){    
00383             buf[(x0 - y)*2 + (y0 + x)*256] = color >> 8;
00384             buf[(x0 - y)*2 + (y0 + x)*256 + 1] = color;
00385         }
00386         if(x0-x >= 0 & x0-x <128 & y0+y >= 0 & y0+y<128){    
00387             buf[(x0 - x)*2 + (y0 + y)*256] = color >> 8;
00388             buf[(x0 - x)*2 + (y0 + y)*256 + 1] = color;
00389         }
00390         if(x0-x >= 0 & x0-x <128 & y0-y >= 0 & y0-y<128){    
00391             buf[(x0 - x)*2 + (y0 - y)*256] = color >> 8;
00392             buf[(x0 - x)*2 + (y0 - y)*256 + 1] = color;
00393         }
00394         if(x0-y >= 0 & x0-y <128 & y0-x >= 0 & y0-x<128){    
00395             buf[(x0 - y)*2 + (y0 - x)*256] = color >> 8;
00396             buf[(x0 - y)*2 + (y0 - x)*256 + 1] = color;
00397         }
00398         if(x0+y >= 0 & x0+y <128 & y0-x >= 0 & y0-x<128){    
00399             buf[(x0 + y)*2 + (y0 - x)*256] = color >> 8;
00400             buf[(x0 + y)*2 + (y0 - x)*256 + 1] = color;
00401         }
00402         if(x0+x >= 0 & x0+x <128 & y0-y >= 0 & y0-y<128){    
00403             buf[(x0 + x)*2 + (y0 - y)*256] = color >> 8;
00404             buf[(x0 + x)*2 + (y0 - y)*256 + 1] = color;
00405         }
00406         y += 1;
00407         if(err <= 0){
00408             err += 2*y + 1;
00409         }
00410         if(err > 0){
00411             x -= 1;
00412             err -= 2*x + 1;
00413         }
00414     }
00415 }
00416 
00417 void SSD1351::fillCircle(int16_t x0, int16_t y0, uint16_t radius, uint16_t color){
00418     int16_t x = radius;
00419     int16_t y = 0;
00420     int16_t err = 0;
00421     
00422     while(x >= y){
00423         drawLine(x0,y0+y,x0+x,y0+y,color);
00424         drawLine(x0,y0+y,x0-x,y0+y,color);
00425         drawLine(x0,y0-y,x0+x,y0-y,color);
00426         drawLine(x0,y0-y,x0-x,y0-y,color);
00427         
00428         drawLine(x0,y0+x,x0+y,y0+x,color);
00429         drawLine(x0,y0+x,x0-y,y0+x,color);
00430         drawLine(x0,y0-x,x0+y,y0-x,color);
00431         drawLine(x0,y0-x,x0-y,y0-x,color);
00432         
00433         y += 1;
00434         if(err <= 0){
00435             err += 2*y + 1;
00436         }
00437         if(err > 0){
00438             x -= 1;
00439             err -= 2*x + 1;
00440         }
00441     }
00442 }
00443 
00444 //Display a sprite on the screen
00445 void SSD1351::drawSpritePtr(const uint16_t s[] ,int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t mask){
00446     int16_t start = y*256 + x*2;
00447     uint16_t xs = 0;
00448     uint16_t xe = 0;
00449     uint16_t ys = 0;
00450     uint16_t ye = 0;
00451     
00452     if(x < 0){
00453         xs = -x;
00454     }
00455     if(y < 0){
00456         ys = -y;
00457     }
00458     if(x+w > 127){
00459         xe = x+w-128;
00460     }
00461     if(y+h > 127){
00462         ye = y+h-128;
00463     }
00464     
00465     for(uint16_t j=0+ys; j<h-ye; j++){
00466         for(uint16_t i=0+xs; i<w-xe; i++){
00467             if(s[j*w +i] != mask){
00468                 buf[start +j*256 +i*2] = s[j*w +i] >> 8;
00469                 buf[start +j*256 +i*2 +1] = s[j*w +i];
00470             }
00471         }
00472     }
00473 }
00474 
00475 //Fill the collision mask with data
00476 void SSD1351::fillCMask(uint8_t state){
00477     for(uint16_t i=0; i < 128*128; i++){
00478         collisionmask[i] = state;
00479     }
00480 }
00481 
00482 //Write data to the collision mask
00483 void SSD1351::drawCMask(const uint16_t s[], int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t mask, uint8_t state){
00484     int16_t start = y*128 + x;
00485     uint16_t xs = 0;
00486     uint16_t xe = 0;
00487     uint16_t ys = 0;
00488     uint16_t ye = 0;
00489     
00490     if(x < 0){
00491         xs = -x;
00492     }
00493     if(y < 0){
00494         ys = -y;
00495     }
00496     if(x+w > 127){
00497         xe = x+w-128;
00498     }
00499     if(y+h > 127){
00500         ye = y+h-128;
00501     }
00502     
00503     for(uint16_t j=0+ys; j<h-ye; j++){
00504         for(uint16_t i=0+xs; i<w-xe; i++){
00505             if(s[j*w +i] != mask){
00506                 collisionmask[start +j*128 +i] = state;
00507             }
00508         }
00509     }
00510 }
00511 
00512 //Check if a sprite is colliding with anything
00513 uint8_t SSD1351::checkCollision(const uint16_t s[], int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t mask){
00514     int16_t start = y*128 + x;
00515     uint16_t xs = 0;
00516     uint16_t xe = 0;
00517     uint16_t ys = 0;
00518     uint16_t ye = 0;
00519     
00520     if(x < 0){
00521         xs = -x;
00522     }
00523     if(y < 0){
00524         ys = -y;
00525     }
00526     if(x+w > 127){
00527         xe = x+w-128;
00528     }
00529     if(y+h > 127){
00530         ye = y+h-128;
00531     }
00532     
00533     for(uint16_t j=0+ys; j<h-ye; j++){
00534         for(uint16_t i=0+xs; i<w-xe; i++){
00535             if((s[j*w +i] != mask) && (collisionmask[start+j*128+i] != 0x00)){
00536                 return collisionmask[start+j*128+i];
00537             }
00538         }
00539     }
00540     return 0;
00541 }
00542 
00543 //Draw a character
00544 void SSD1351::drawChar(char c, int16_t x, int16_t y, uint16_t color, uint8_t zoom){
00545     int16_t start = y*256 + x*2;
00546     uint16_t xs = 0;
00547     uint16_t xe = 0;
00548     uint16_t ys = 0;
00549     uint16_t ye = 0;
00550     
00551     if(x < 0){
00552         xs = -x;
00553     }
00554     if(y < 0){
00555         ys = -y;
00556     }
00557     if(x+3*zoom > 127){
00558         xe = x+3*zoom-128;
00559     }
00560     if(y+5*zoom > 127){
00561         ye = y+5*zoom-128;
00562     }
00563     
00564     uint16_t letter = font[c];
00565     for(uint8_t j=0+ys;j<5*zoom-ye;j++){
00566         for(uint8_t i=0+xs;i<3*zoom-xe;i++){
00567             if(((letter << (uint8_t(i/zoom)+3*uint8_t(j/zoom))) & 0x8000) == 0x8000){
00568                 for(uint8_t k=0; k<zoom; k++){
00569                     buf[start+j*256+i*2] = color >> 8;
00570                     buf[start+j*256+i*2 + 1] = color;
00571                 }
00572             }
00573         }
00574     }
00575 }
00576 
00577 //Draw a bunch of characters
00578 void SSD1351::printText(const char c[], int16_t x, int16_t y, uint16_t color, uint8_t zoom){
00579     for(uint16_t i=0; i<strlen(c);i++){
00580         drawChar(c[i], x+i*4*zoom, y, color, zoom);
00581     }
00582 }