Keith Mitchell / Hexidraw

Dependents:   Hexidraw_Demo Hexiwear-FinalProject_v2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hexidraw.cpp Source File

hexidraw.cpp

00001 #include "oled_info.h"
00002 #include "hexidraw.h"
00003 
00004 #include "mbed.h"
00005 
00006 #include <math.h>
00007 
00008 /*
00009     Command descriptions from:
00010         https://cdn-shop.adafruit.com/datasheets/SSD1351-Revision+1.3.pdf
00011 */
00012 
00013 OLED::OLED () :
00014     _spi(oled_sdi_pin, NC, oled_sck_pin),
00015     _cs(oled_cs_pin),
00016     _reset(oled_rst_pin),
00017     _dc(oled_dc_pin)
00018 {
00019     if(USE_BUFFER) {
00020         for(uint16_t i = 0; i < OLED_WIDTH * OLED_HEIGHT; ++ i) {
00021             displayBuffer[i] = BLACK;
00022         }
00023     }
00024 }
00025 
00026 void OLED::begin()
00027 {
00028 
00029 #if 0
00030     // set pin directions
00031     pinMode(_rs, OUTPUT);
00032 
00033     if (_sclk) {
00034         pinMode(_sclk, OUTPUT);
00035 
00036         pinMode(_sid, OUTPUT);
00037     } else {
00038         // using the hardware SPI
00039         SPI.begin();
00040         SPI.setDataMode(SPI_MODE3);
00041     }
00042 
00043     // Toggle RST low to reset; CS low so it'll listen to us
00044     pinMode(_cs, OUTPUT);
00045     digitalWrite(_cs, LOW);
00046 
00047     if (_rst) {
00048         pinMode(_rst, OUTPUT);
00049         digitalWrite(_rst, HIGH);
00050         delay(500);
00051         digitalWrite(_rst, LOW);
00052         delay(500);
00053         digitalWrite(_rst, HIGH);
00054         delay(500);
00055     }
00056 #endif
00057     DigitalOut BOOSTEN(oled_power_enable);   //Enable OLED
00058 
00059     //Set SPI modes
00060 //    _spi.format(8,3);
00061     _spi.frequency(8000000);
00062 
00063     _dc =0;
00064     BOOSTEN = 0;
00065     wait(0.1f);
00066     _reset = 0 ;
00067     wait(0.1f);
00068     _reset = 1 ;
00069     wait(0.1f);
00070     BOOSTEN = 1;
00071 
00072     writeCommand(OLED_CMD_SET_CMD_LOCK);
00073     writeData(0x12);
00074 
00075     writeCommand(OLED_CMD_SET_CMD_LOCK);
00076     writeData(0xB1);
00077 
00078     writeCommand(OLED_CMD_DISPLAYOFF);
00079 
00080 
00081     writeCommand(OLED_CMD_SET_OSC_FREQ_AND_CLOCKDIV);
00082     writeData(0xF1);
00083 
00084     writeCommand(OLED_CMD_SET_MUX_RATIO);
00085     writeData(0x5F);
00086 
00087     writeCommand(OLED_CMD_SET_REMAP);
00088     writeData(OLED_REMAP_SETTINGS);
00089 
00090     writeCommand(OLED_CMD_SET_COLUMN);
00091     writeData(0x00);
00092     writeData(0x5F);
00093 
00094     writeCommand(OLED_CMD_SET_ROW);
00095     writeData(0x00);
00096     writeData(0x5F);
00097 
00098     writeCommand(OLED_CMD_STARTLINE);
00099     writeData(0x80);
00100 
00101     writeCommand(OLED_CMD_DISPLAYOFFSET);
00102     writeData(0x60);
00103 
00104     writeCommand(OLED_CMD_PRECHARGE);
00105     writeData(0x32);
00106 
00107     writeCommand(OLED_CMD_VCOMH);
00108     writeData(0x05);
00109 
00110     writeCommand(OLED_CMD_NORMALDISPLAY);
00111 
00112     writeCommand(OLED_CMD_CONTRASTABC);
00113     writeData(0x8A);
00114     writeData(0x51);
00115     writeData(0x8A);
00116 
00117     writeCommand(OLED_CMD_CONTRASTMASTER);
00118     writeData(0xCF);
00119 
00120     writeCommand(OLED_CMD_SETVSL);
00121     writeData(0xA0);
00122     writeData(0xB5);
00123     writeData(0x55);
00124 
00125     writeCommand(OLED_CMD_PRECHARGE2);
00126     writeData(0x01);
00127 
00128     writeCommand(OLED_CMD_DISPLAYON);
00129 }
00130 
00131 void OLED::writeCommand(uint8_t code)
00132 {
00133     _dc = 0;
00134 
00135     _cs = 0;
00136     _spi.write(code);
00137     _cs = 1;
00138 }
00139 
00140 void OLED::writeData(uint8_t value)
00141 {
00142     _dc = 1;
00143 
00144     _cs = 0;
00145     _spi.write(value);
00146     _cs = 1;
00147 }
00148 //Turns on OLED sleep mode
00149 void OLED::sleep()
00150 {
00151     writeCommand(0xAE);
00152 }
00153 //Turns off OLED sleep mode
00154 void OLED::wake()
00155 {
00156     writeCommand(0xAF);
00157 }
00158 
00159 void OLED::draw()
00160 {
00161     if(USE_BUFFER) {
00162         writeCommand(OLED_CMD_SET_COLUMN);
00163         writeData(16);
00164         writeData(111);
00165         writeCommand(OLED_CMD_SET_ROW);
00166         writeData(0);
00167         writeData(95);
00168         writeCommand(OLED_CMD_WRITERAM);
00169 
00170         _dc = 1;
00171         _cs = 0;
00172 
00173         for(uint32_t i = 0; i < OLED_WIDTH * OLED_HEIGHT; ++ i) {
00174             writeData(displayBuffer[i] >> 8);
00175             writeData(displayBuffer[i]);
00176         }
00177 
00178         _cs = 1;
00179     }
00180 }
00181 
00182 void OLED::cursor(int x, int y)   //goTo
00183 {
00184     if ((x >= OLED_WIDTH) || (y >= OLED_HEIGHT)) return;
00185     x+=OLED_COL_OFFSET;
00186     // set x and y coordinate
00187     writeCommand(OLED_CMD_SET_COLUMN);
00188     writeData(x);
00189     writeData(OLED_WIDTH-1);
00190 
00191     writeCommand(OLED_CMD_SET_ROW);
00192     writeData(y);
00193     writeData(OLED_HEIGHT-1);
00194 
00195     writeCommand(OLED_CMD_WRITERAM);
00196 }
00197 
00198 void OLED::pixel(int16_t x, int16_t y, uint16_t color)
00199 {
00200     // Bounds check.
00201     if ((x >= OLED_WIDTH) || (y >= OLED_HEIGHT)) return;
00202     if ((x < 0) || (y < 0)) return;
00203     if(!USE_BUFFER) {
00204         cursor(x, y);
00205 
00206         writeCommand(OLED_CMD_WRITERAM);
00207         _dc = 1;
00208         _cs = 0;
00209 
00210         writeData(color >> 8);
00211         writeData(color);
00212 
00213         _cs = 1;
00214     } else {
00215         displayBuffer[x+OLED_WIDTH*y] = color;
00216     }
00217 }
00218 
00219 void OLED::clear (uint16_t color)
00220 {
00221     rect(0, 0, OLED_WIDTH, OLED_HEIGHT, color);
00222 }
00223 void OLED::rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t fillcolor)
00224 {
00225     // Bounds check
00226     if ((x >= OLED_WIDTH) || (y >= OLED_HEIGHT))
00227         return;
00228 
00229     // Y bounds check
00230     if (y+h > OLED_HEIGHT) {
00231         h = OLED_HEIGHT - y - 1;
00232     }
00233 
00234     // X bounds check
00235     if (x+w > OLED_WIDTH) {
00236         w = OLED_WIDTH - x - 1;
00237     }
00238     if(!USE_BUFFER) {
00239         x+= OLED_COL_OFFSET;
00240 
00241         // set location
00242         writeCommand(OLED_CMD_SET_COLUMN);
00243         writeData(x);
00244         writeData(x+(w-1));
00245         writeCommand(OLED_CMD_SET_ROW);
00246         writeData(y);
00247         writeData(y+(h-1));
00248         // fill!
00249         writeCommand(OLED_CMD_WRITERAM);
00250 
00251         for (uint16_t i=0; i < w*h; i++) {
00252             writeData(fillcolor >> 8);
00253             writeData(fillcolor);
00254         }
00255     } else {
00256         for(uint16_t _w = 0; _w < w; ++_w) {
00257             for(uint16_t _h = 0; _h < h; ++_h) {
00258                 displayBuffer[((x+_w)+OLED_WIDTH*(y+_h))] = fillcolor;
00259             }
00260         }
00261     }
00262 }
00263 
00264 void OLED::circle(uint16_t x, uint16_t y, uint16_t radius, uint16_t color, uint16_t width)
00265 {
00266     const float DEG2RAD = 3.14159f/180;
00267     for(uint16_t r = 0; r < width; ++r) {
00268         for(uint16_t i = 0; i < 360; ++i) {
00269             float degInRad = i*DEG2RAD;
00270             uint16_t x2 = x + cos(degInRad) * (radius+r);
00271             uint16_t y2 = y + sin(degInRad) * (radius+r);
00272             if(USE_BUFFER) {
00273                 displayBuffer[((x2)+OLED_WIDTH*(y2))] = color;
00274             } else {
00275                 pixel(x2, y2, color);
00276             }
00277         }
00278     }
00279 }
00280 
00281 void buffer_swap(
00282     uint16_t* imgDst,
00283     const uint8_t* imgSrc,
00284     uint16_t imgSize
00285 )
00286 {
00287     for ( int var = 0; var < imgSize; var++ ) {
00288         *imgDst = *imgSrc << 8;
00289         imgSrc++;
00290         *imgDst |= *imgSrc;
00291         imgDst++;
00292         imgSrc++;
00293     }
00294 }
00295 
00296 
00297 void OLED::image (uint16_t x, uint16_t y, const uint8_t* image)
00298 {
00299     x+= OLED_COL_OFFSET;
00300     //cursor(x, y);
00301 
00302     uint16_t w = image[2];
00303     uint16_t h = image[4];
00304 
00305     uint16_t image_data_size = w * h * OLED_BYTES_PER_PIXEL;
00306 
00307     if(!USE_BUFFER) {
00308         writeCommand(OLED_CMD_SET_COLUMN);
00309         writeData(x);
00310         writeData(x+(w-1));
00311         writeCommand(OLED_CMD_SET_ROW);
00312         writeData(y);
00313         writeData(y+(h-1));
00314 
00315         writeCommand(OLED_CMD_WRITERAM);
00316         _dc = 1;
00317         _cs = 0;
00318 
00319         const uint8_t* buffer = OLED_SKIP_IMAGE_HEADER(image);
00320 
00321         for ( uint32_t i = 0; i < image_data_size; i++) {
00322             _spi.write(*buffer);
00323             buffer += 1;
00324         }
00325 
00326     } else {
00327         const uint8_t* buffer = OLED_SKIP_IMAGE_HEADER(image);
00328         buffer_swap(displayBuffer, buffer, image_data_size);
00329     }
00330 
00331 }
00332 
00333 
00334 void OLED::dim()
00335 {
00336     for ( int i = 0; i < 16; i++ ) {
00337         writeCommand( OLED_CMD_CONTRASTMASTER);
00338         writeData( 0xC0 | (0xF-i));
00339         wait( 20 );
00340     }
00341 }
00342 
00343 void OLED::hline(uint16_t x, uint16_t y, uint16_t width, uint16_t color, uint16_t thickness)
00344 {
00345     if(!USE_BUFFER) {
00346         //x+= OLED_COL_OFFSET;
00347         // set location
00348         writeCommand(OLED_CMD_SET_COLUMN);
00349         writeData(x);
00350         writeData(x+width-1);
00351         writeCommand(OLED_CMD_SET_ROW);
00352         writeData(y);
00353         writeData(y+thickness-1);
00354         // fill!
00355         writeCommand(OLED_CMD_WRITERAM);
00356 
00357         for (uint16_t i=0; i < width*thickness; i++) {
00358             writeData(color >> 8);
00359             writeData(color);
00360         }
00361     } else {
00362 
00363         for (uint16_t w=0; w < width; w++) {
00364             for (uint16_t h=0; h < thickness; h++) {
00365                 displayBuffer[((x+w)+OLED_WIDTH*(y+h))] = color;
00366             }
00367         }
00368     }
00369 
00370 }
00371 
00372 void OLED::vline(uint16_t x, uint16_t y, uint16_t height, uint16_t color, uint16_t thickness)
00373 {
00374     if(!USE_BUFFER) {
00375         x+= OLED_COL_OFFSET;
00376         // set location
00377         writeCommand(OLED_CMD_SET_COLUMN);
00378         writeData(x);
00379         writeData(x+thickness-1);
00380         writeCommand(OLED_CMD_SET_ROW);
00381         writeData(y);
00382         writeData(y+height-1);
00383         // fill!
00384         writeCommand(OLED_CMD_WRITERAM);
00385 
00386         for (uint16_t i=0; i < height*thickness; i++) {
00387             writeData(color >> 8);
00388             writeData(color);
00389         }
00390     } else {
00391         for (uint16_t w=0; w < thickness; w++) {
00392             for (uint16_t h=0; h < height; h++) {
00393                 displayBuffer[((x+w)+OLED_WIDTH*(y+h))] = color;
00394             }
00395         }
00396     }
00397 }
00398 
00399 void OLED::text(uint16_t x, uint16_t y, const uint8_t* text, const uint8_t* font, uint16_t color)
00400 {
00401 
00402     x += OLED_COL_OFFSET;
00403     uint8_t pad = 2;
00404 
00405     uint8_t firstChar = font[2];
00406     uint8_t charHeight    = font[6];    
00407     
00408     uint16_t current_char = 0;
00409     while(text[current_char] != 0) {
00410         
00411         ++current_char;
00412     }
00413 }
00414 
00415 uint16_t Color565(uint8_t r, uint8_t g, uint8_t b)
00416 {
00417     uint16_t c;
00418     c = r >> 3;
00419     c <<= 6;
00420     c |= g >> 2;
00421     c <<= 5;
00422     c |= b >> 3;
00423 
00424     return c;
00425 }