sandeep ponnuru / SFE_MicroOLED_debugPrint

Fork of SFE_MicroOLED by Nenad Milosevic

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SFE_MicroOLED.cpp Source File

SFE_MicroOLED.cpp

00001 /****************************************************************************** 
00002 SFE_MicroOLED.cpp
00003 Main source code for the MicroOLED mbed Library
00004 Jim Lindblom @ SparkFun Electronics
00005 October 26, 2014
00006 https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
00007 Adapted for mbed by Nenad Milosevic
00008 March, 2015
00009 Adapted for 64x32 oled my Goran Mahovlić
00010 This file defines the hardware SPI interface for the Micro OLED Breakout.
00011 Development environment specifics:
00012 Various suitable mbed platforms
00013 Micro OLED Breakout v1.0
00014 This code was heavily based around the MicroView library, written by GeekAmmo
00015 (https://github.com/geekammo/MicroView-Arduino-Library), and released under 
00016 the terms of the GNU General Public License as published by the Free Software 
00017 Foundation, either version 3 of the License, or (at your option) any later 
00018 version.
00019 This program is distributed in the hope that it will be useful,
00020 but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 GNU General Public License for more details.
00023 You should have received a copy of the GNU General Public License
00024 along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025 ******************************************************************************/
00026 
00027 #include "mbed.h"
00028 #include <stdarg.h>
00029 #include "SFE_MicroOLED.h"
00030 
00031 // Add header of the fonts here.
00032 #include "font5x7.h"
00033 #include "font8x16.h"
00034 #include "fontlargenumber.h"
00035 #include "7segment.h"
00036 
00037 // Change the total fonts included
00038 #define TOTALFONTS      4
00039 extern Serial pc;
00040 // Add the font name as declared in the header file.
00041 unsigned const char *MicroOLED::fontsPointer[]={
00042     font5x7
00043     ,font8x16
00044     ,sevensegment
00045     ,fontlargenumber
00046 };
00047 
00048 /** \brief MicroOLED screen buffer.
00049 Page buffer LCDWIDTH x LCDHEIGHT divided by 8
00050 Page buffer is required because in SPI mode, the host cannot read the SSD1306's GDRAM of the controller.  This page buffer serves as a scratch RAM for graphical functions.  All drawing function will first be drawn on this page buffer, only upon calling display() function will transfer the page buffer to the actual LCD controller's memory.
00051 */
00052 static uint8_t screenmemory [LCDWIDTH * LCDHEIGHT / 8]; 
00053     /* SSD1306 Memory organised in 128 horizontal pixel and 8 rows of byte
00054      B  B .............B  -----
00055      y  y .............y        \
00056      t  t .............t         \
00057      e  e .............e          \
00058      0  1 .............127         \
00059                                     \
00060      D0 D0.............D0            \
00061      D1 D1.............D1            / ROW 0
00062      D2 D2.............D2           /
00063      D3 D3.............D3          /
00064      D4 D4.............D4         /
00065      D5 D5.............D5        /
00066      D6 D6.............D6       /
00067      D7 D7.............D7  ----
00068     */
00069 
00070 /** \brief Initialisation of MicroOLED Library.
00071     Setup IO pins and parameters for SPI then send initialisation commands to the SSD1306 controller inside the OLED. 
00072 */
00073 void MicroOLED::init(int spi_mode, int spi_freq) 
00074 {   
00075      //pc.printf("Trying to init OLED\n");
00076      
00077     // default 5x7 font
00078     setFontType(0);
00079     setColor(WHITE);
00080     setDrawMode(NORM);
00081     setCursor(0,0);
00082     //pc.printf("Set fonts and modes\n");
00083   
00084     memset(screenmemory,0,(LCDWIDTH * LCDHEIGHT / 8));  // initially clear Page buffer
00085     //pc.printf("Acc screen mem and init to 0\n");
00086 
00087     // Initialize the SPI library:
00088     dcPin = 0;
00089     csPin = 1;
00090     miol_spi.format(8, spi_mode);   // 8 Bit wide SPI and Mode (0 - 3)
00091     miol_spi.frequency(spi_freq);   // SPI speed in Hz
00092      //pc.printf("spi done\n");
00093     // Display reset routine
00094     rstPin = 1; // Initially set RST HIGH
00095     wait_ms(5); // VDD (3.3V) goes high at start, lets just chill for 5 ms
00096     rstPin = 0; // Bring RST low, reset the display
00097     wait_ms(10);    // wait 10ms
00098     rstPin = 1; // Set RST HIGH, bring out of reset
00099     wait_ms(5); // wait 5ms
00100 
00101     //pc.printf("Reset done\n");
00102 //  Original Espruino commands
00103 //  uint8_t initCmds[] = { 0xAe,0xD5,0x80,0xA8,31,0xD3,0x0,0x40,0x8D,0x14,0x20,0x00,0xA1,0xC8,0xDA,0x12,0x81,0xCF,0xD9,0xF1,0xDb,0x40,0xA4,0xA6,0xAf};
00104  
00105 //  Latest Espruino commands
00106     uint8_t initCmds[] = { 0xAe,0xD5,0x80,0xA8,31,0xD3,0x0,0x40,0x8D,0x14,0x20,0x01,0xA1,0xC8,0xDA,0x12,0x81,0xCF,0xD9,0xF1,0xDb,0x40,0xA4,0xA6,0xAf };
00107 
00108 // Init commands from the OLED Display datasheet
00109     uint8_t initCmdsOLED_SPEC[] = { 0xAE,    /*display off*/        
00110                                     0x00,    /*set lower column address*/        
00111                                     0x12,    /*set higher column address*/ 
00112                                     0x00,    /*set display start line*/ 
00113                                     0xB0,    /*set page address*/ 
00114                                     0x81,    /*contract control*/ 
00115                                     0x4f,        /*128*/  
00116                                     0xA1,    /*set segment remap*/ 
00117                                     0xA6,    /*normal / reverse*/ 
00118                                     0xA8,    /*multiplex ratio*/ 
00119                                     0x1F,        /*duty  =  1/32*/  
00120                                     0xC8,    /*Com scan direction*/ 
00121                                     0xD3,    /*set display offset*/ 
00122                                     0x00, 
00123                                     0xD5,    /*set osc division*/ 
00124                                     0x80,     
00125                                     0xD9,    /*set pre-charge period*/ 
00126                                     0x1f, 
00127                                     0xDA,    /*set COM pins*/ 
00128                                     0x12, 
00129                                     0xdb,    /*set vcomh*/ 
00130                                     0x40, 
00131                                     0x8d,    /*set charge pump enable*/ 
00132                                     0x10, 
00133                                     0xAF    /*display ON*/   }; 
00134 
00135     //pc.printf("before command\n"); 
00136     command (initCmdsOLED_SPEC,sizeof(initCmds));
00137 /*  
00138     miol_spi.write(0x21);
00139     miol_spi.write(0);
00140     miol_spi.write(127);
00141     miol_spi.write(0x22);
00142     miol_spi.write(0);
00143     miol_spi.write(7);  
00144     
00145 */
00146     //pc.printf("command done 1\n"); 
00147     command(MEMORYMODE, 0);
00148     clear(ALL);                     // Erase hardware memory inside the OLED controller to avoid random data in memory.
00149  // command(DISPLAYON);
00150     //pc.printf("finsihed all tasks of init\n"); 
00151 }
00152 
00153 /** \brief Send the display command byte(s)
00154     
00155     Send command(s) via SPI to SSD1306 controller.
00156 */
00157 void MicroOLED::command(uint8_t c) {
00158     
00159     dcPin = 0;  // DC pin LOW for a command
00160     csPin = 0;  // SS LOW to initialize transfer
00161     miol_spi.write(c);          // Transfer the command byte
00162     csPin = 1;  // SS HIGH to end transfer
00163  
00164 }
00165  
00166 void MicroOLED::command(uint8_t c1, uint8_t c2) {
00167     
00168     dcPin = 0;  // DC pin LOW for a command
00169     csPin = 0;  // SS LOW to initialize transfer
00170     miol_spi.write(c1);         // Transfer the command byte
00171     miol_spi.write(c2);         // Transfer the first parameter
00172     csPin = 1;  // SS HIGH to end transfer
00173  
00174 }
00175  
00176 void MicroOLED::command(uint8_t c1, uint8_t c2, uint8_t c3) {
00177     
00178     dcPin = 0;  // DC pin LOW for a command
00179     csPin = 0;  // SS LOW to initialize transfer
00180     miol_spi.write(c1);         // Transfer the command byte
00181     miol_spi.write(c2);         // Transfer the first parameter
00182     miol_spi.write(c3);         // Transfer the second parameter
00183     csPin = 1;  // SS HIGH to end transfer
00184  
00185 }
00186  
00187 void MicroOLED::command(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4, uint8_t c5, uint8_t c6, uint8_t c7, uint8_t c8) {
00188     
00189     dcPin = 0;  // DC pin LOW for a command
00190     csPin = 0;  // SS LOW to initialize transfer
00191     miol_spi.write(c1);         // Transfer the command byte
00192     miol_spi.write(c2);         // Transfer the first parameter
00193     miol_spi.write(c3);         // Transfer the second parameter
00194     miol_spi.write(c4);         // Transfer the third parameter
00195     miol_spi.write(c5);         // Transfer the fourth parameter
00196     miol_spi.write(c6);         // Transfer the fifth parameter
00197     miol_spi.write(c7);         // Transfer the sixth parameter
00198     miol_spi.write(c8);         // Transfer the seventh parameter
00199     csPin = 1;  // SS HIGH to end transfer
00200  
00201 }
00202  
00203 void MicroOLED::command(uint8_t cmds[],int length) {
00204     
00205    // pc.printf("inside command function \n");
00206     dcPin = 0;  // DC pin LOW for a command
00207     csPin = 0;  // SS LOW to initialize transfer
00208     for(int i=0;i<length;i++)
00209     {
00210             //pc.printf("inside loop %d,%d  \n",i,cmds[i]);
00211 
00212         miol_spi.write(cmds[i]);
00213     }
00214     csPin = 1;  // SS HIGH to end transfer
00215  
00216 } 
00217  
00218 /** \brief Clear screen buffer or SSD1306's memory.
00219  
00220     To clear all GDRAM inside the LCD controller, pass in the variable mode = ALL and to clear screen page buffer pass in the variable mode = PAGE.
00221 */
00222 void MicroOLED::clear(uint8_t mode) {
00223     if (mode==ALL) 
00224     {
00225         csPin = 0;
00226         dcPin = 0;
00227         
00228         for (int b=0;b<4;b++) 
00229         {   
00230             dcPin = 0;
00231             miol_spi.write(0xb0+b);
00232             miol_spi.write(0x00);
00233             miol_spi.write(0x12);
00234             dcPin = 1;
00235             for (int i = 0; i < 64; i++) 
00236             {
00237                 miol_spi.write(0);
00238             }
00239         }
00240         csPin = 1;
00241     }
00242     else
00243     {
00244         memset(screenmemory,0,(LCDWIDTH * LCDPAGES));
00245         //display();
00246     }
00247 }
00248  
00249 /** \brief Clear or replace screen buffer or SSD1306's memory with a character. 
00250  
00251     To clear GDRAM inside the LCD controller, pass in the variable mode = ALL with c character and to clear screen page buffer, pass in the variable mode = PAGE with c character.
00252 */
00253 void MicroOLED::clear(uint8_t mode, uint8_t c) {
00254     if (mode==ALL) {
00255         csPin = 0;
00256         dcPin = 0;
00257         
00258         for (int b=0;b<4;b++) 
00259         {   
00260             dcPin = 0;
00261             miol_spi.write(0xb0+b);
00262             miol_spi.write(0x00);
00263             miol_spi.write(0x12);
00264             dcPin = 1;
00265             for (int i = 0; i < 64; i++) 
00266             {
00267                 miol_spi.write(c);
00268             }
00269         }
00270         csPin = 1;
00271 
00272     }
00273     else
00274     {
00275         memset(screenmemory,c,LCDWIDTH * LCDPAGES);
00276         display();
00277     }   
00278 }
00279  
00280 /** \brief Invert display.
00281  
00282     The WHITE color of the display will turn to BLACK and the BLACK will turn to WHITE.
00283 */
00284 void MicroOLED::invert(boolean inv) {
00285     if (inv)
00286     command(INVERTDISPLAY);
00287     else
00288     command(NORMALDISPLAY);
00289 }
00290  
00291 /** \brief Set contrast.
00292  
00293     OLED contract value from 0 to 255. Note: Contrast level is not very obvious.
00294 */
00295 void MicroOLED::contrast(uint8_t contrast) {
00296     command(SETCONTRAST, contrast);         // 0x81
00297 }
00298  
00299 /** \brief Transfer display memory.
00300  
00301     Bulk move the screen buffer to the SSD1306 controller's memory so that images/graphics drawn on the screen buffer will be displayed on the OLED.
00302 */
00303 void MicroOLED::display(void) {
00304 
00305     csPin = 0;
00306     dcPin = 0;
00307     
00308 
00309     
00310     for (int b=0;b<4;b++) 
00311     {   
00312         dcPin = 0;
00313         miol_spi.write(0xb0+b);
00314         miol_spi.write(0x00);
00315         miol_spi.write(0x12);
00316         dcPin = 1;
00317         for (int i = 0; i < 64; i++) 
00318         {
00319             miol_spi.write(screenmemory[i+64*b]);
00320         }
00321     }
00322     csPin = 1;
00323 }
00324  
00325 /*
00326     Classic text print functions.
00327 */
00328  
00329 void MicroOLED::putc(char c) {
00330     if (c == '\n') {
00331         cursorY += fontHeight;
00332         cursorX  = 0;
00333     } else if (c == '\r') {
00334         // skip 
00335     } else {
00336         drawChar(cursorX, cursorY, (uint8_t)c, foreColor, drawMode);
00337         cursorX += fontWidth+1;
00338         if ((cursorX > (LCDWIDTH - fontWidth))) {
00339             cursorY += fontHeight;
00340             cursorX = 0;
00341         }
00342     }
00343 }
00344  
00345 void MicroOLED::puts(const char *cstring) {
00346     while (*cstring != 0) {
00347         putc(*cstring++);
00348     }
00349 }
00350  
00351 void MicroOLED::printf(const char *format, ...)
00352 {
00353     static char buffer[128];
00354     
00355     va_list args;
00356     va_start(args, format);
00357     vsprintf(buffer, format, args);
00358     va_end(args);
00359     
00360     char *c = (char *)&buffer;
00361     while (*c != 0)
00362     {
00363         putc(*c++);
00364     }
00365 }
00366  
00367 /** \brief Set cursor position.
00368  
00369 MicroOLED's cursor position to x,y.
00370 */
00371 void MicroOLED::setCursor(uint8_t x, uint8_t y) {
00372     cursorX=x;
00373     cursorY=y;
00374 }
00375  
00376 /** \brief Draw pixel.
00377  
00378 Draw pixel using the current fore color and current draw mode in the screen buffer's x,y position.
00379 */
00380 void MicroOLED::pixel(uint8_t x, uint8_t y) {
00381     pixel(x,y,foreColor,drawMode);
00382 }
00383  
00384 /** \brief Draw pixel with color and mode.
00385  
00386 Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode.
00387 */
00388 void MicroOLED::pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) {
00389     if ((x>=LCDWIDTH) || (y>=LCDHEIGHT))
00390     return;
00391     
00392     if (mode==XOR) {
00393         if (color==WHITE)
00394         screenmemory[x+ (y/8)*LCDWIDTH] ^= _BV((y%8));
00395     }
00396     else {
00397         if (color==WHITE)
00398         screenmemory[x+ (y/8)*LCDWIDTH] |= _BV((y%8));
00399         else
00400         screenmemory[x+ (y/8)*LCDWIDTH] &= ~_BV((y%8)); 
00401     }
00402 }
00403  
00404 /** \brief Draw line.
00405  
00406 Draw line using current fore color and current draw mode from x0,y0 to x1,y1 of the screen buffer.
00407 */
00408 void MicroOLED::line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) {
00409     line(x0,y0,x1,y1,foreColor,drawMode);
00410 }
00411  
00412 /** \brief Draw line with color and mode.
00413  
00414 Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.
00415 */
00416 void MicroOLED::line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) {
00417     uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
00418     if (steep) {
00419         swap(x0, y0);
00420         swap(x1, y1);
00421     }
00422  
00423     if (x0 > x1) {
00424         swap(x0, x1);
00425         swap(y0, y1);
00426     }
00427  
00428     uint8_t dx, dy;
00429     dx = x1 - x0;
00430     dy = abs(y1 - y0);
00431  
00432     int8_t err = dx / 2;
00433     int8_t ystep;
00434  
00435     if (y0 < y1) {
00436         ystep = 1;
00437     } else {
00438         ystep = -1;}
00439  
00440     for (; x0<x1; x0++) {
00441         if (steep) {
00442             pixel(y0, x0, color, mode);
00443         } else {
00444             pixel(x0, y0, color, mode);
00445         }
00446         err -= dy;
00447         if (err < 0) {
00448             y0 += ystep;
00449             err += dx;
00450         }
00451     }   
00452 }
00453  
00454 /** \brief Draw horizontal line.
00455  
00456 Draw horizontal line using current fore color and current draw mode from x,y to x+width,y of the screen buffer.
00457 */
00458 void MicroOLED::lineH(uint8_t x, uint8_t y, uint8_t width) {
00459     line(x,y,x+width,y,foreColor,drawMode);
00460 }
00461  
00462 /** \brief Draw horizontal line with color and mode.
00463  
00464 Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.
00465 */
00466 void MicroOLED::lineH(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode) {
00467     line(x,y,x+width,y,color,mode);
00468 }
00469  
00470 /** \brief Draw vertical line.
00471  
00472 Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.
00473 */
00474 void MicroOLED::lineV(uint8_t x, uint8_t y, uint8_t height) {
00475     line(x,y,x,y+height,foreColor,drawMode);
00476 }
00477  
00478 /** \brief Draw vertical line with color and mode.
00479  
00480 Draw vertical line using color and mode from x,y to x,y+height of the screen buffer.
00481 */
00482 void MicroOLED::lineV(uint8_t x, uint8_t y, uint8_t height, uint8_t color, uint8_t mode) {
00483     line(x,y,x,y+height,color,mode);
00484 }
00485  
00486 /** \brief Draw rectangle.
00487  
00488 Draw rectangle using current fore color and current draw mode from x,y to x+width,y+height of the screen buffer.
00489 */
00490 void MicroOLED::rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
00491     rect(x,y,width,height,foreColor,drawMode);
00492 }
00493  
00494 /** \brief Draw rectangle with color and mode.
00495  
00496 Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
00497 */
00498 void MicroOLED::rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color , uint8_t mode) {
00499     uint8_t tempHeight;
00500     
00501     lineH(x,y, width, color, mode);
00502     lineH(x,y+height-1, width, color, mode);
00503     
00504     tempHeight=height-2;
00505     
00506     // skip drawing vertical lines to avoid overlapping of pixel that will 
00507     // affect XOR plot if no pixel in between horizontal lines      
00508     if (tempHeight<1) return;           
00509  
00510     lineV(x,y+1, tempHeight, color, mode);
00511     lineV(x+width-1, y+1, tempHeight, color, mode);
00512 }
00513  
00514 /** \brief Draw filled rectangle.
00515  
00516 Draw filled rectangle using current fore color and current draw mode from x,y to x+width,y+height of the screen buffer.
00517 */
00518 void MicroOLED::rectFill(uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
00519     rectFill(x,y,width,height,foreColor,drawMode);
00520 }
00521  
00522 /** \brief Draw filled rectangle with color and mode.
00523  
00524 Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
00525 */  
00526 void MicroOLED::rectFill(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color , uint8_t mode) {
00527     // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
00528     for (int i=x; i<x+width;i++) {
00529         lineV(i,y, height, color, mode);
00530     }
00531 }
00532  
00533 /** \brief Draw circle.
00534  
00535     Draw circle with radius using current fore color and current draw mode at x,y of the screen buffer.
00536 */
00537 void MicroOLED::circle(uint8_t x0, uint8_t y0, uint8_t radius) {
00538     circle(x0,y0,radius,foreColor,drawMode);
00539 }
00540  
00541 /** \brief Draw circle with color and mode.
00542  
00543 Draw circle with radius using color and mode at x,y of the screen buffer.
00544 */
00545 void MicroOLED::circle(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode) {
00546     //TODO - find a way to check for no overlapping of pixels so that XOR draw mode will work perfectly 
00547     int8_t f = 1 - radius;
00548     int8_t ddF_x = 1;
00549     int8_t ddF_y = -2 * radius;
00550     int8_t x = 0;
00551     int8_t y = radius;
00552  
00553     pixel(x0, y0+radius, color, mode);
00554     pixel(x0, y0-radius, color, mode);
00555     pixel(x0+radius, y0, color, mode);
00556     pixel(x0-radius, y0, color, mode);
00557  
00558     while (x<y) {
00559         if (f >= 0) {
00560             y--;
00561             ddF_y += 2;
00562             f += ddF_y;
00563         }
00564         x++;
00565         ddF_x += 2;
00566         f += ddF_x;
00567  
00568         pixel(x0 + x, y0 + y, color, mode);
00569         pixel(x0 - x, y0 + y, color, mode);
00570         pixel(x0 + x, y0 - y, color, mode);
00571         pixel(x0 - x, y0 - y, color, mode);
00572         
00573         pixel(x0 + y, y0 + x, color, mode);
00574         pixel(x0 - y, y0 + x, color, mode);
00575         pixel(x0 + y, y0 - x, color, mode);
00576         pixel(x0 - y, y0 - x, color, mode);
00577         
00578     }
00579 }
00580  
00581 /** \brief Draw filled circle.
00582  
00583     Draw filled circle with radius using current fore color and current draw mode at x,y of the screen buffer.
00584 */
00585 void MicroOLED::circleFill(uint8_t x0, uint8_t y0, uint8_t radius) {
00586     circleFill(x0,y0,radius,foreColor,drawMode);
00587 }
00588  
00589 /** \brief Draw filled circle with color and mode.
00590  
00591     Draw filled circle with radius using color and mode at x,y of the screen buffer.
00592 */
00593 void MicroOLED::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode) {
00594     // TODO - - find a way to check for no overlapping of pixels so that XOR draw mode will work perfectly 
00595     int8_t f = 1 - radius;
00596     int8_t ddF_x = 1;
00597     int8_t ddF_y = -2 * radius;
00598     int8_t x = 0;
00599     int8_t y = radius;
00600  
00601     // Temporary disable fill circle for XOR mode.
00602     if (mode==XOR) return;
00603     
00604     for (uint8_t i=y0-radius; i<=y0+radius; i++) {
00605         pixel(x0, i, color, mode);
00606     }
00607  
00608     while (x<y) {
00609         if (f >= 0) {
00610             y--;
00611             ddF_y += 2;
00612             f += ddF_y;
00613         }
00614         x++;
00615         ddF_x += 2;
00616         f += ddF_x;
00617  
00618         for (uint8_t i=y0-y; i<=y0+y; i++) {
00619             pixel(x0+x, i, color, mode);
00620             pixel(x0-x, i, color, mode);
00621         } 
00622         for (uint8_t i=y0-x; i<=y0+x; i++) {
00623             pixel(x0+y, i, color, mode);
00624             pixel(x0-y, i, color, mode);
00625         }    
00626     }
00627 }
00628  
00629 /** \brief Get LCD height.
00630  
00631     The height of the LCD return as byte.
00632 */
00633 uint8_t MicroOLED::getLCDHeight(void) {
00634     return LCDHEIGHT;
00635 }
00636  
00637 /** \brief Get LCD width.
00638  
00639     The width of the LCD return as byte.
00640 */  
00641 uint8_t MicroOLED::getLCDWidth(void) {
00642     return LCDWIDTH;
00643 }
00644  
00645 /** \brief Get font width.
00646  
00647     The cucrrent font's width return as byte.
00648 */  
00649 uint8_t MicroOLED::getFontWidth(void) {
00650     return fontWidth;
00651 }
00652  
00653 /** \brief Get font height.
00654  
00655     The current font's height return as byte.
00656 */
00657 uint8_t MicroOLED::getFontHeight(void) {
00658     return fontHeight;
00659 }
00660  
00661 /** \brief Get font starting character.
00662  
00663     Return the starting ASCII character of the currnet font, not all fonts start with ASCII character 0. Custom fonts can start from any ASCII character.
00664 */
00665 uint8_t MicroOLED::getFontStartChar(void) {
00666     return fontStartChar;
00667 }
00668  
00669 /** \brief Get font total characters.
00670  
00671     Return the total characters of the current font.
00672 */
00673 uint8_t MicroOLED::getFontTotalChar(void) {
00674     return fontTotalChar;
00675 }
00676  
00677 /** \brief Get total fonts.
00678  
00679     Return the total number of fonts loaded into the MicroOLED's flash memory.
00680 */
00681 uint8_t MicroOLED::getTotalFonts(void) {
00682     return TOTALFONTS;
00683 }
00684  
00685 /** \brief Get font type.
00686  
00687     Return the font type number of the current font.
00688 */
00689 uint8_t MicroOLED::getFontType(void) {
00690     return fontType;
00691 }
00692  
00693 /** \brief Set font type.
00694  
00695     Set the current font type number, ie changing to different fonts base on the type provided.
00696 */
00697 uint8_t MicroOLED::setFontType(uint8_t type) {
00698     if (type>=TOTALFONTS)
00699     return false;
00700  
00701     fontType = type;
00702     fontWidth = *(fontsPointer[fontType]+0);
00703     fontHeight = *(fontsPointer[fontType]+1);
00704     fontStartChar = *(fontsPointer[fontType]+2);
00705     fontTotalChar = *(fontsPointer[fontType]+3);
00706     fontMapWidth = (*(fontsPointer[fontType]+4) * 100) + *(fontsPointer[fontType]+5); // two bytes values into integer 16
00707     return true;
00708 }
00709  
00710 /** \brief Set color.
00711  
00712     Set the current draw's color. Only WHITE and BLACK available.
00713 */
00714 void MicroOLED::setColor(uint8_t color) {
00715     foreColor=color;
00716 }
00717  
00718 /** \brief Set draw mode.
00719  
00720     Set current draw mode with NORM or XOR.
00721 */
00722 void MicroOLED::setDrawMode(uint8_t mode) {
00723     drawMode=mode;
00724 }
00725  
00726 /** \brief Draw character.
00727  
00728     Draw character c using current color and current draw mode at x,y.
00729 */
00730 void  MicroOLED::drawChar(uint8_t x, uint8_t y, uint8_t c) {
00731     drawChar(x,y,c,foreColor,drawMode);
00732 }
00733  
00734 /** \brief Draw character with color and mode.
00735  
00736     Draw character c using color and draw mode at x,y.
00737 */
00738 void  MicroOLED::drawChar(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode) {
00739     // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels
00740  
00741     uint8_t rowsToDraw,row, tempC;
00742     uint8_t i,j,temp;
00743     uint16_t charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition;
00744     
00745     if ((c<fontStartChar) || (c>(fontStartChar+fontTotalChar-1)))       // no bitmap for the required c
00746     return;
00747     
00748     tempC=c-fontStartChar;
00749  
00750     // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn
00751     rowsToDraw=fontHeight/8;    // 8 is LCD's page size, see SSD1306 datasheet
00752     if (rowsToDraw<=1) rowsToDraw=1;
00753  
00754     // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw
00755     if (rowsToDraw==1) {
00756         for  (i=0;i<fontWidth+1;i++) {
00757             if (i==fontWidth) // this is done in a weird way because for 5x7 font, there is no margin, this code add a margin after col 5
00758             temp=0;
00759             else
00760             temp = *(fontsPointer[fontType]+FONTHEADERSIZE+(tempC*fontWidth)+i);
00761             
00762             for (j=0;j<8;j++) {         // 8 is the LCD's page height (see datasheet for explanation)
00763                 if (temp & 0x1) {
00764                     pixel(x+i, y+j, color,mode);
00765                 }
00766                 else {
00767                     pixel(x+i, y+j, !color,mode);
00768                 }
00769                 
00770                 temp >>=1;
00771             }
00772         }
00773         return;
00774     }
00775  
00776     // font height over 8 bit
00777     // take character "0" ASCII 48 as example
00778     charPerBitmapRow=fontMapWidth/fontWidth;  // 256/8 =32 char per row
00779     charColPositionOnBitmap=tempC % charPerBitmapRow;  // =16
00780     charRowPositionOnBitmap=int(tempC/charPerBitmapRow); // =1
00781     charBitmapStartPosition=(charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ;
00782  
00783     // each row on LCD is 8 bit height (see datasheet for explanation)
00784     for(row=0;row<rowsToDraw;row++) {
00785         for (i=0; i<fontWidth;i++) {
00786             temp = *(fontsPointer[fontType]+FONTHEADERSIZE+(charBitmapStartPosition+i+(row*fontMapWidth)));
00787             for (j=0;j<8;j++) {         // 8 is the LCD's page height (see datasheet for explanation)
00788                 if (temp & 0x1) {
00789                     pixel(x+i,y+j+(row*8), color, mode);
00790                 }
00791                 else {
00792                     pixel(x+i,y+j+(row*8), !color, mode);
00793                 }
00794                 temp >>=1;
00795             }
00796         }
00797     }
00798  
00799 }
00800  
00801 /** \brief Stop scrolling.
00802  
00803     Stop the scrolling of graphics on the OLED.
00804 */
00805 void MicroOLED::scrollStop(void){
00806     command(DEACTIVATESCROLL);
00807 }
00808  
00809 /** \brief Right scrolling.
00810  
00811 Set row start to row stop on the OLED to scroll right. Refer to http://learn.microview.io/intro/general-overview-of-microview.html for explanation of the rows.
00812 */
00813 void MicroOLED::scrollRight(uint8_t start, uint8_t stop){
00814     if (stop<start)     // stop must be larger or equal to start
00815     return;
00816     scrollStop();       // need to disable scrolling before starting to avoid memory corrupt
00817     command(RIGHTHORIZONTALSCROLL, 0x00, start, 0x07, stop, 0x00, 0xFF, ACTIVATESCROLL); // scroll speed frames , TODO
00818 }
00819  
00820 /** \brief Left scrolling.
00821     Set row start to row stop on the OLED to scroll left. Refer to http://learn.microview.io/intro/general-overview-of-microview.html for explanation of the rows.
00822 */
00823 void MicroOLED::scrollLeft(uint8_t start, uint8_t stop){
00824     if (stop<start)     // stop must be larger or equal to start
00825     return;
00826     scrollStop();       // need to disable scrolling before starting to avoid memory corrupt
00827     command(LEFTHORIZONTALSCROLL, 0x00, start, 0x07, stop, 0x00, 0xFF, ACTIVATESCROLL); // scroll speed frames , TODO
00828 }
00829  
00830 /** \brief Vertical flip.
00831  
00832 Flip the graphics on the OLED vertically.
00833 */
00834 void MicroOLED::flipVertical(boolean flip) {
00835     if (flip) {
00836         command(COMSCANINC);
00837     }
00838     else {
00839         command(COMSCANDEC);
00840     }
00841 }
00842  
00843 /** \brief Horizontal flip.
00844  
00845     Flip the graphics on the OLED horizontally.
00846 */  
00847 void MicroOLED::flipHorizontal(boolean flip) {
00848     if (flip) {
00849         command(SEGREMAP | 0x0);
00850     }
00851     else {
00852         command(SEGREMAP | 0x1);
00853     }
00854 }
00855  
00856 /*
00857     Return a pointer to the start of the RAM screen buffer for direct access.
00858 */
00859 uint8_t *MicroOLED::getScreenBuffer(void) {
00860     return screenmemory;
00861 }
00862  
00863 /*
00864 Draw Bitmap image on screen. The array for the bitmap can be stored in main program file, so user don't have to mess with the library files. 
00865 To use, create const uint8_t array that is LCDWIDTH x LCDHEIGHT pixels (LCDWIDTH * LCDHEIGHT / 8 bytes). Then call .drawBitmap and pass it the array. 
00866 */  
00867 void MicroOLED::drawBitmap(const uint8_t * bitArray)
00868 {
00869     for (int i=0; i<(LCDWIDTH * LCDHEIGHT / 8); i++)
00870         screenmemory[i] = bitArray[i];
00871 }
00872 
00873 /** \brief Set SSD1306 page address.
00874     Send page address command and address to the SSD1306 OLED controller.
00875 */
00876 void MicroOLED::setPageAddress(uint8_t add) {
00877     command(SETPAGE|add);
00878     return;
00879 }
00880 
00881 /** \brief Set SSD1306 column address.
00882     Send column address command and address to the SSD1306 OLED controller.
00883 */
00884 void MicroOLED::setColumnAddress(uint8_t add) {
00885     command((SETHIGHCOLUMN|(add>>4))+0x02, SETLOWCOLUMN|(0x0f&add));
00886     return;
00887 }