Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Fri Jul 15 2022 01:37:24 by
1.7.2