diff --git a/MicroView.cpp b/MicroView.cpp index 0ce324f..778cb21 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -115,7 +115,7 @@ static uint8_t screenmemory [] = { /** \brief Initialisation of MicroView Library. - Setup IO pins for SPI port then send initialisation commands to the SSD1306 controller inside the OLED. + Setup IO pins for SPI port then send initialisation commands to the SSD1306 controller inside the OLED. */ void MicroView::begin() { // default 5x7 font @@ -150,17 +150,17 @@ void MicroView::begin() { delay(10); // Init sequence for 64x48 OLED module -// command(DISPLAYOFF); // 0xAE -// command(SETDISPLAYCLOCKDIV, 0x80); // 0xD5 / the suggested ratio 0x80 + // command(DISPLAYOFF); // 0xAE + // command(SETDISPLAYCLOCKDIV, 0x80); // 0xD5 / the suggested ratio 0x80 command(SETMULTIPLEX, 0x2F); // 0xA8 -// command(SETDISPLAYOFFSET, 0x0); // 0xD3 / no offset -// command(SETSTARTLINE | 0x0); // 0x40 / line #0 + // command(SETDISPLAYOFFSET, 0x0); // 0xD3 / no offset + // command(SETSTARTLINE | 0x0); // 0x40 / line #0 command(CHARGEPUMP, 0x14); // 0x8D / enable charge pump -// command(NORMALDISPLAY); // 0xA6 -// command(DISPLAYALLONRESUME); // 0xA4 + // command(NORMALDISPLAY); // 0xA6 + // command(DISPLAYALLONRESUME); // 0xA4 command(SEGREMAP | 0x1); command(COMSCANDEC); -// command(SETCOMPINS, 0x12); // 0xDA + // command(SETCOMPINS, 0x12); // 0xDA command(SETCONTRAST, 0x8F); // 0x81 command(SETPRECHARGE, 0xF1); // 0xD9 command(SETVCOMDESELECT, 0x40); // 0xDB @@ -168,14 +168,14 @@ void MicroView::begin() { clear(ALL); // Erase hardware memory inside the OLED controller to avoid random data in memory. - Serial.begin(115200); + // Serial.begin(115200); // removed the Serial.begin() so that user can decide their own baud rate. } /** \brief Power off the OLED display. - Reset display control signals and - prepare the SSD1306 controller for power off, - then power off the 3.3V regulator. + Reset display control signals and + prepare the SSD1306 controller for power off, + then power off the 3.3V regulator. */ void MicroView::end() { DCLOW; // Just in case @@ -190,7 +190,7 @@ void MicroView::end() { /** \brief Send 1 command byte. - Send 1 command byte via SPI to SSD1306 controller. + Send 1 command byte via SPI to SSD1306 controller. */ void MicroView::command(uint8_t c) { MVSPI.packetBegin(); @@ -200,7 +200,7 @@ void MicroView::command(uint8_t c) { /** \brief Send 2 command bytes. - Send 2 command bytes via SPI to SSD1306 controller. + Send 2 command bytes via SPI to SSD1306 controller. */ void MicroView::command(uint8_t c1, uint8_t c2) { MVSPI.packetBegin(); @@ -212,7 +212,7 @@ void MicroView::command(uint8_t c1, uint8_t c2) { /** \brief Send 3 command bytes. - Send 3 command bytes via SPI to SSD1306 controller. + Send 3 command bytes via SPI to SSD1306 controller. */ void MicroView::command(uint8_t c1, uint8_t c2, uint8_t c3) { MVSPI.packetBegin(); @@ -226,7 +226,7 @@ void MicroView::command(uint8_t c1, uint8_t c2, uint8_t c3) { /** \brief SPI data. - Send 1 data byte via SPI to SSD1306 controller. + Send 1 data byte via SPI to SSD1306 controller. */ void MicroView::data(uint8_t c) { MVSPI.packetBegin(); @@ -237,7 +237,7 @@ void MicroView::data(uint8_t c) { /** \brief Set SSD1306 page address. - Send page address command and address to the SSD1306 OLED controller. + Send page address command and address to the SSD1306 OLED controller. */ void MicroView::setPageAddress(uint8_t add) { command(SETPAGE|add); @@ -246,7 +246,7 @@ void MicroView::setPageAddress(uint8_t add) { /** \brief Set SSD1306 column address. - Send column address command and address to the SSD1306 OLED controller. + Send column address command and address to the SSD1306 OLED controller. */ void MicroView::setColumnAddress(uint8_t add) { command((SETHIGHCOLUMN|(add>>4))+0x02, SETLOWCOLUMN|(0x0f&add)); @@ -254,8 +254,8 @@ void MicroView::setColumnAddress(uint8_t add) { } /** \brief Clear screen buffer or SSD1306's memory. - - To clear GDRAM inside the LCD controller, pass in the variable mode = ALL and to clear screen page buffer pass in the variable mode = PAGE. + + To clear GDRAM inside the LCD controller, pass in the variable mode = ALL and to clear screen page buffer pass in the variable mode = PAGE. */ void MicroView::clear(uint8_t mode) { if (mode==ALL) { @@ -311,7 +311,7 @@ void MicroView::clear(uint8_t mode, uint8_t c) { /** \brief Invert display. - The WHITE color of the display will turn to BLACK and the BLACK will turn to WHITE. + The WHITE color of the display will turn to BLACK and the BLACK will turn to WHITE. */ void MicroView::invert(boolean inv) { if (inv) @@ -322,7 +322,7 @@ void MicroView::invert(boolean inv) { /** \brief Set contrast. - OLED contrast value from 0 to 255. Note: Contrast level is not very obvious. + OLED contrast value from 0 to 255. Note: Contrast level is not very obvious. */ void MicroView::contrast(uint8_t contrast) { command(SETCONTRAST, contrast); // 0x81 @@ -330,13 +330,13 @@ void MicroView::contrast(uint8_t contrast) { /** \brief Transfer display memory. - 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. + 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. */ void MicroView::display(void) { command(SETADDRESSMODE, 0); // Set horizontal addressing mode command(SETCOLUMNBOUNDS, - LCDCOLUMNOFFSET, - LCDCOLUMNOFFSET + LCDWIDTH - 1); // Set width + LCDCOLUMNOFFSET, + LCDCOLUMNOFFSET + LCDWIDTH - 1); // Set width command(SETPAGEBOUNDS, 0, LCDPAGES - 1); // Set height MVSPI.packetBegin(); @@ -354,466 +354,466 @@ void MicroView::display(void) { //#if ARDUINO >= 100 /** \brief Override Arduino's Print. - Arduino's print overridden so that we can use uView.print(). + Arduino's print overridden so that we can use uView.print(). */ size_t MicroView::write(uint8_t c) { -//#else -// void MicroView::write(uint8_t c) { -//#endif - if (c == '\n') { + //#else + // void MicroView::write(uint8_t c) { + //#endif + if (c == '\n') { + cursorY += fontHeight; + cursorX = 0; + } else if (c == '\r') { + // skip + } else { + drawChar(cursorX, cursorY, c, foreColor, drawMode); + cursorX += fontWidth+1; + if ((cursorX > (LCDWIDTH - fontWidth))) { cursorY += fontHeight; - cursorX = 0; - } else if (c == '\r') { - // skip - } else { - drawChar(cursorX, cursorY, c, foreColor, drawMode); - cursorX += fontWidth+1; - if ((cursorX > (LCDWIDTH - fontWidth))) { - cursorY += fontHeight; - cursorX = 0; - } + cursorX = 0; } -//#if ARDUINO >= 100 - return 1; -//#endif } + //#if ARDUINO >= 100 + return 1; + //#endif +} /** \brief Set cursor position. - MicroView's cursor position to x,y. + MicroView's cursor position to x,y. */ - void MicroView::setCursor(uint8_t x, uint8_t y) { - cursorX=x; - cursorY=y; - } +void MicroView::setCursor(uint8_t x, uint8_t y) { + cursorX=x; + cursorY=y; +} /** \brief Draw pixel. - Draw pixel using the current fore color and current draw mode in the screen buffer's x,y position. + Draw pixel using the current fore color and current draw mode in the screen buffer's x,y position. */ - void MicroView::pixel(uint8_t x, uint8_t y) { - pixel(x,y,foreColor,drawMode); - } +void MicroView::pixel(uint8_t x, uint8_t y) { + pixel(x,y,foreColor,drawMode); +} /** \brief Draw pixel with color and mode. - Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode. + Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode. */ - void MicroView::pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) { - if ((x<0) || (x>=LCDWIDTH) || (y<0) || (y>=LCDHEIGHT)) - return; - - if (mode==XOR) { - if (color==WHITE) - screenmemory[x+ (y/8)*LCDWIDTH] ^= _BV((y%8)); - } - else { - if (color==WHITE) - screenmemory[x+ (y/8)*LCDWIDTH] |= _BV((y%8)); - else - screenmemory[x+ (y/8)*LCDWIDTH] &= ~_BV((y%8)); - } - - //display(); +void MicroView::pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) { + if ((x<0) || (x>=LCDWIDTH) || (y<0) || (y>=LCDHEIGHT)) + return; + + if (mode==XOR) { + if (color==WHITE) + screenmemory[x+ (y/8)*LCDWIDTH] ^= _BV((y%8)); } + else { + if (color==WHITE) + screenmemory[x+ (y/8)*LCDWIDTH] |= _BV((y%8)); + else + screenmemory[x+ (y/8)*LCDWIDTH] &= ~_BV((y%8)); + } + + //display(); +} /** \brief Draw line. - Draw line using current fore color and current draw mode from x0,y0 to x1,y1 of the screen buffer. + Draw line using current fore color and current draw mode from x0,y0 to x1,y1 of the screen buffer. */ - void MicroView::line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { - line(x0,y0,x1,y1,foreColor,drawMode); - } +void MicroView::line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { + line(x0,y0,x1,y1,foreColor,drawMode); +} /** \brief Draw line with color and mode. - Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer. + Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer. */ - void MicroView::line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) { - uint8_t steep = abs(y1 - y0) > abs(x1 - x0); - if (steep) { - swap(x0, y0); - swap(x1, y1); - } - - if (x0 > x1) { - swap(x0, x1); - swap(y0, y1); - } - - uint8_t dx, dy; - dx = x1 - x0; - dy = abs(y1 - y0); - - int8_t err = dx / 2; - int8_t ystep; - - if (y0 < y1) { - ystep = 1; - } else { - ystep = -1;} - - for (; x0 abs(x1 - x0); + if (steep) { + swap(x0, y0); + swap(x1, y1); } + if (x0 > x1) { + swap(x0, x1); + swap(y0, y1); + } + + uint8_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int8_t err = dx / 2; + int8_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1;} + + for (; x0= 0) { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - - pixel(x0 + x, y0 + y, color, mode); - pixel(x0 - x, y0 + y, color, mode); - pixel(x0 + x, y0 - y, color, mode); - pixel(x0 - x, y0 - y, color, mode); - - pixel(x0 + y, y0 + x, color, mode); - pixel(x0 - y, y0 + x, color, mode); - pixel(x0 + y, y0 - x, color, mode); - pixel(x0 - y, y0 - x, color, mode); - + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; } + x++; + ddF_x += 2; + f += ddF_x; + + pixel(x0 + x, y0 + y, color, mode); + pixel(x0 - x, y0 + y, color, mode); + pixel(x0 + x, y0 - y, color, mode); + pixel(x0 - x, y0 - y, color, mode); + + pixel(x0 + y, y0 + x, color, mode); + pixel(x0 - y, y0 + x, color, mode); + pixel(x0 + y, y0 - x, color, mode); + pixel(x0 - y, y0 - x, color, mode); + } +} /** \brief Draw filled circle. - Draw filled circle with radius using current fore color and current draw mode at x,y of the screen buffer. + Draw filled circle with radius using current fore color and current draw mode at x,y of the screen buffer. */ - void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius) { - circleFill(x0,y0,radius,foreColor,drawMode); - } +void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius) { + circleFill(x0,y0,radius,foreColor,drawMode); +} /** \brief Draw filled circle with color and mode. - Draw filled circle with radius using color and mode at x,y of the screen buffer. + Draw filled circle with radius using color and mode at x,y of the screen buffer. */ - void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode) { - // TODO - - find a way to check for no overlapping of pixels so that XOR draw mode will work perfectly - int8_t f = 1 - radius; - int8_t ddF_x = 1; - int8_t ddF_y = -2 * radius; - int8_t x = 0; - int8_t y = radius; +void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode) { + // TODO - - find a way to check for no overlapping of pixels so that XOR draw mode will work perfectly + int8_t f = 1 - radius; + int8_t ddF_x = 1; + int8_t ddF_y = -2 * radius; + int8_t x = 0; + int8_t y = radius; - // Temporary disable fill circle for XOR mode. - if (mode==XOR) return; - - for (uint8_t i=y0-radius; i<=y0+radius; i++) { - pixel(x0, i, color, mode); - } - - while (x= 0) { - y--; - ddF_y += 2; - f += ddF_y; - } - x++; - ddF_x += 2; - f += ddF_x; - - for (uint8_t i=y0-y; i<=y0+y; i++) { - pixel(x0+x, i, color, mode); - pixel(x0-x, i, color, mode); - } - for (uint8_t i=y0-x; i<=y0+x; i++) { - pixel(x0+y, i, color, mode); - pixel(x0-y, i, color, mode); - } - } + // Temporary disable fill circle for XOR mode. + if (mode==XOR) return; + + for (uint8_t i=y0-radius; i<=y0+radius; i++) { + pixel(x0, i, color, mode); } + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + for (uint8_t i=y0-y; i<=y0+y; i++) { + pixel(x0+x, i, color, mode); + pixel(x0-x, i, color, mode); + } + for (uint8_t i=y0-x; i<=y0+x; i++) { + pixel(x0+y, i, color, mode); + pixel(x0-y, i, color, mode); + } + } +} + /** \brief Get LCD height. - The height of the LCD return as byte. + The height of the LCD return as byte. */ - uint8_t MicroView::getLCDHeight(void) { - return LCDHEIGHT; - } +uint8_t MicroView::getLCDHeight(void) { + return LCDHEIGHT; +} /** \brief Get LCD width. - The width of the LCD return as byte. + The width of the LCD return as byte. */ - uint8_t MicroView::getLCDWidth(void) { - return LCDWIDTH; - } +uint8_t MicroView::getLCDWidth(void) { + return LCDWIDTH; +} /** \brief Get font width. - The cucrrent font's width return as byte. + The cucrrent font's width return as byte. */ - uint8_t MicroView::getFontWidth(void) { - return fontWidth; - } +uint8_t MicroView::getFontWidth(void) { + return fontWidth; +} /** \brief Get font height. - The current font's height return as byte. + The current font's height return as byte. */ - uint8_t MicroView::getFontHeight(void) { - return fontHeight; - } +uint8_t MicroView::getFontHeight(void) { + return fontHeight; +} /** \brief Get font starting character. - 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. + 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. */ - uint8_t MicroView::getFontStartChar(void) { - return fontStartChar; - } +uint8_t MicroView::getFontStartChar(void) { + return fontStartChar; +} /** \brief Get font total characters. - Return the total characters of the current font. + Return the total characters of the current font. */ - uint8_t MicroView::getFontTotalChar(void) { - return fontTotalChar; - } +uint8_t MicroView::getFontTotalChar(void) { + return fontTotalChar; +} /** \brief Get total fonts. - Return the total number of fonts loaded into the MicroView's flash memory. + Return the total number of fonts loaded into the MicroView's flash memory. */ - uint8_t MicroView::getTotalFonts(void) { - return TOTALFONTS; - } +uint8_t MicroView::getTotalFonts(void) { + return TOTALFONTS; +} /** \brief Get font type. - Return the font type number of the current font. + Return the font type number of the current font. */ - uint8_t MicroView::getFontType(void) { - return fontType; - } +uint8_t MicroView::getFontType(void) { + return fontType; +} /** \brief Set font type. - Set the current font type number, ie changing to different fonts base on the type provided. + Set the current font type number, ie changing to different fonts base on the type provided. */ - uint8_t MicroView::setFontType(uint8_t type) { - if ((type>=TOTALFONTS) || (type<0)) - return false; +uint8_t MicroView::setFontType(uint8_t type) { + if ((type>=TOTALFONTS) || (type<0)) + return false; - fontType=type; - fontWidth=pgm_read_byte(fontsPointer[fontType]+0); - fontHeight=pgm_read_byte(fontsPointer[fontType]+1); - fontStartChar=pgm_read_byte(fontsPointer[fontType]+2); - fontTotalChar=pgm_read_byte(fontsPointer[fontType]+3); - fontMapWidth=(pgm_read_byte(fontsPointer[fontType]+4)*100)+pgm_read_byte(fontsPointer[fontType]+5); // two bytes values into integer 16 - return true; - } + fontType=type; + fontWidth=pgm_read_byte(fontsPointer[fontType]+0); + fontHeight=pgm_read_byte(fontsPointer[fontType]+1); + fontStartChar=pgm_read_byte(fontsPointer[fontType]+2); + fontTotalChar=pgm_read_byte(fontsPointer[fontType]+3); + fontMapWidth=(pgm_read_byte(fontsPointer[fontType]+4)*100)+pgm_read_byte(fontsPointer[fontType]+5); // two bytes values into integer 16 + return true; +} /** \brief Set color. - Set the current draw's color. Only WHITE and BLACK available. + Set the current draw's color. Only WHITE and BLACK available. */ - void MicroView::setColor(uint8_t color) { - foreColor=color; - } +void MicroView::setColor(uint8_t color) { + foreColor=color; +} /** \brief Set draw mode. - Set current draw mode with NORM or XOR. + Set current draw mode with NORM or XOR. */ - void MicroView::setDrawMode(uint8_t mode) { - drawMode=mode; - } +void MicroView::setDrawMode(uint8_t mode) { + drawMode=mode; +} /** \brief Draw character. - Draw character c using current color and current draw mode at x,y. + Draw character c using current color and current draw mode at x,y. */ - void MicroView::drawChar(uint8_t x, uint8_t y, uint8_t c) { - drawChar(x,y,c,foreColor,drawMode); - } +void MicroView::drawChar(uint8_t x, uint8_t y, uint8_t c) { + drawChar(x,y,c,foreColor,drawMode); +} /** \brief Draw character with color and mode. - Draw character c using color and draw mode at x,y. + Draw character c using color and draw mode at x,y. */ - void MicroView::drawChar(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode) { - // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels +void MicroView::drawChar(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode) { + // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels - uint8_t rowsToDraw,row, tempC; - uint8_t i,j,temp; - uint16_t charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition; - - if ((c(fontStartChar+fontTotalChar-1))) // no bitmap for the required c - return; - - tempC=c-fontStartChar; + uint8_t rowsToDraw,row, tempC; + uint8_t i,j,temp; + uint16_t charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition; + + if ((c(fontStartChar+fontTotalChar-1))) // no bitmap for the required c + return; + + tempC=c-fontStartChar; - // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn - rowsToDraw=fontHeight/8; // 8 is LCD's page size, see SSD1306 datasheet - if (rowsToDraw<=1) rowsToDraw=1; + // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn + rowsToDraw=fontHeight/8; // 8 is LCD's page size, see SSD1306 datasheet + if (rowsToDraw<=1) rowsToDraw=1; - // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw - if (rowsToDraw==1) { - for (i=0;i>=1; - } - } - return; - } - - // font height over 8 bit - // take character "0" ASCII 48 as example - charPerBitmapRow=fontMapWidth/fontWidth; // 256/8 =32 char per row - charColPositionOnBitmap=tempC % charPerBitmapRow; // =16 - charRowPositionOnBitmap=int(tempC/charPerBitmapRow); // =1 - charBitmapStartPosition=(charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ; - - // each row on LCD is 8 bit height (see datasheet for explanation) - for(row=0;row>=1; - } + temp >>=1; } } + return; + } - /* + // font height over 8 bit + // take character "0" ASCII 48 as example + charPerBitmapRow=fontMapWidth/fontWidth; // 256/8 =32 char per row + charColPositionOnBitmap=tempC % charPerBitmapRow; // =16 + charRowPositionOnBitmap=int(tempC/charPerBitmapRow); // =1 + charBitmapStartPosition=(charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ; + + // each row on LCD is 8 bit height (see datasheet for explanation) + for(row=0;row>=1; + } + } + } + + /* fast direct memory draw but has a limitation to draw in ROWS // only 1 row to draw for font with 8 bit height if (rowsToDraw==1) { @@ -842,716 +842,724 @@ size_t MicroView::write(uint8_t c) { } */ - } +} /** \brief Stop scrolling. - Stop the scrolling of graphics on the OLED. + Stop the scrolling of graphics on the OLED. */ - void MicroView::scrollStop(void){ - command(DEACTIVATESCROLL); - } +void MicroView::scrollStop(void){ + command(DEACTIVATESCROLL); +} /** \brief Right scrolling. - 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. + 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. */ - void MicroView::scrollRight(uint8_t start, uint8_t stop){ - if (stop0) { - // process Serial data - result=strtok(serInStr,","); - if (result !=NULL) { - temp=atoi(result); - serCmd[index]=(uint8_t)temp & 0xff; // we only need 8 bit number - index++; - for (uint8_t i=0;i0) { + // process Serial data + result=strtok(serInStr,","); + if (result !=NULL) { + temp=atoi(result); + serCmd[index]=(uint8_t)temp & 0xff; // we only need 8 bit number + index++; + for (uint8_t i=0;i15) { + for (int i=150;i<=390;i+=15) { // Minor tick from 150 degree to 390 degree degreeSec=i*(PI/180); - fromSecX = cos(degreeSec) * (radius / 1.5); - fromSecY = sin(degreeSec) * (radius / 1.5); + fromSecX = cos(degreeSec) * (radius / 1.3); + fromSecY = sin(degreeSec) * (radius / 1.3); toSecX = cos(degreeSec) * (radius / 1); toSecY = sin(degreeSec) * (radius / 1); uView.line(1+offsetX+fromSecX,1+offsetY+fromSecY,1+offsetX+toSecX,1+offsetY+toSecY); } - - if(radius>15) { - for (int i=150;i<=390;i+=15) { // Minor tick from 150 degree to 390 degree - degreeSec=i*(PI/180); - fromSecX = cos(degreeSec) * (radius / 1.3); - fromSecY = sin(degreeSec) * (radius / 1.3); - toSecX = cos(degreeSec) * (radius / 1); - toSecY = sin(degreeSec) * (radius / 1); - uView.line(1+offsetX+fromSecX,1+offsetY+fromSecY,1+offsetX+toSecX,1+offsetY+toSecY); - } - } } +} /** \brief Draw widget value. - Convert the current value of the widget and draw the ticker representing the value. + Convert the current value of the widget and draw the ticker representing the value. */ - void MicroViewGauge::draw() { - uint8_t offsetX, offsetY; - float degreeSec, toSecX, toSecY; +void MicroViewGauge::draw() { + uint8_t offsetX, offsetY; + float degreeSec, toSecX, toSecY; - char strBuffer[5]; - offsetX=getX(); - offsetY=getY(); + char strBuffer[5]; + offsetX=getX(); + offsetY=getY(); - if (needFirstDraw) { - degreeSec = (((float)(prevValue-getMinValue())/(float)(getMaxValue()-getMinValue()))*240); // total 240 degree in the widget - degreeSec = (degreeSec+150) * (PI/180); // 150 degree starting point - toSecX = cos(degreeSec) * (radius / 1.2); - toSecY = sin(degreeSec) * (radius / 1.2); - uView.line(offsetX,offsetY,1+offsetX+toSecX,1+offsetY+toSecY, WHITE,XOR); - sprintf(strBuffer,"%4d", prevValue); // we need to force 4 digit so that blank space will cover larger value - needFirstDraw=false; - } - else { + if (needFirstDraw) { + degreeSec = (((float)(prevValue-getMinValue())/(float)(getMaxValue()-getMinValue()))*240); // total 240 degree in the widget + degreeSec = (degreeSec+150) * (PI/180); // 150 degree starting point + toSecX = cos(degreeSec) * (radius / 1.2); + toSecY = sin(degreeSec) * (radius / 1.2); + uView.line(offsetX,offsetY,1+offsetX+toSecX,1+offsetY+toSecY, WHITE,XOR); + sprintf(strBuffer,"%4d", prevValue); // we need to force 4 digit so that blank space will cover larger value + needFirstDraw=false; + } + else { + if (needToDrawPrev) { // Draw previous pointer in XOR mode to erase it degreeSec = (((float)(prevValue-getMinValue())/(float)(getMaxValue()-getMinValue()))*240); // total 240 degree in the widget degreeSec = (degreeSec+150) * (PI/180); toSecX = cos(degreeSec) * (radius / 1.2); toSecY = sin(degreeSec) * (radius / 1.2); uView.line(offsetX,offsetY,1+offsetX+toSecX,1+offsetY+toSecY, WHITE,XOR); - - degreeSec = (((float)(getValue()-getMinValue())/(float)(getMaxValue()-getMinValue()))*240); // total 240 degree in the widget - degreeSec = (degreeSec+150) * (PI/180); // 150 degree starting point - toSecX = cos(degreeSec) * (radius / 1.2); - toSecY = sin(degreeSec) * (radius / 1.2); - uView.line(offsetX,offsetY,1+offsetX+toSecX,1+offsetY+toSecY, WHITE,XOR); - - sprintf(strBuffer,"%4d", getValue()); // we need to force 4 digit so that blank space will cover larger value - prevValue=getValue(); } - - // Draw value - if(style>0) - uView.setCursor(offsetX-10,offsetY+10); - else - uView.setCursor(offsetX-11,offsetY+11); - uView.print(strBuffer); + // draw current pointer + degreeSec = (((float)(getValue()-getMinValue())/(float)(getMaxValue()-getMinValue()))*240); // total 240 degree in the widget + degreeSec = (degreeSec+150) * (PI/180); // 150 degree starting point + toSecX = cos(degreeSec) * (radius / 1.2); + toSecY = sin(degreeSec) * (radius / 1.2); + uView.line(offsetX,offsetY,1+offsetX+toSecX,1+offsetY+toSecY, WHITE,XOR); + + sprintf(strBuffer,"%4d", getValue()); // we need to force 4 digit so that blank space will cover larger value + prevValue=getValue(); + needToDrawPrev=true; } - // ------------------------------------------------------------------------------------- - // Gauge Widget - end - // ------------------------------------------------------------------------------------- + // Draw value + if(style>0) + uView.setCursor(offsetX-10,offsetY+10); + else + uView.setCursor(offsetX-11,offsetY+11); + + uView.print(strBuffer); +} + +// ------------------------------------------------------------------------------------- +// Gauge Widget - end +// ------------------------------------------------------------------------------------- /** \brief SPI Initialisation. - Setup SCK, MOSI, SS and DC pins for SPI transmission. + Setup SCK, MOSI, SS and DC pins for SPI transmission. */ - void MVSPIClass::begin() { - // Set SS to high so the display will be "deselected" by default - SSHIGH; - // Warning: if the SS pin ever becomes a LOW INPUT then SPI - // automatically switches to Slave. - // This should not occur with the MicroView as nothing can drive the pin. +void MVSPIClass::begin() { + // Set SS to high so the display will be "deselected" by default + SSHIGH; + // Warning: if the SS pin ever becomes a LOW INPUT then SPI + // automatically switches to Slave. + // This should not occur with the MicroView as nothing can drive the pin. - // Set DC low for command mode, where it should always default to unless - // data is being transmitted. - DCLOW; + // Set DC low for command mode, where it should always default to unless + // data is being transmitted. + DCLOW; - // Set SCK and MOSI to be outputs and low when SPI is disabled. - digitalWrite(SCK, LOW); - digitalWrite(MOSI, LOW); - pinMode(SCK, OUTPUT); - pinMode(MOSI, OUTPUT); + // Set SCK and MOSI to be outputs and low when SPI is disabled. + digitalWrite(SCK, LOW); + digitalWrite(MOSI, LOW); + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); - // Set SPI master mode. Don't enable SPI at this time. - SPCR |= _BV(MSTR); - } + // Set SPI master mode. Don't enable SPI at this time. + SPCR |= _BV(MSTR); +} /** \brief End SPI. */ - void MVSPIClass::end() { - SPCR &= ~_BV(SPE); - // SCK and MOSI should already be low but set them again, to be sure. - digitalWrite(SCK, LOW); - digitalWrite(MOSI, LOW); - pinMode(SCK, OUTPUT); - pinMode(MOSI, OUTPUT); - } +void MVSPIClass::end() { + SPCR &= ~_BV(SPE); + // SCK and MOSI should already be low but set them again, to be sure. + digitalWrite(SCK, LOW); + digitalWrite(MOSI, LOW); + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); +} /** \brief Set up SPI for transmitting - Pepare the SPI interface for transmitting on or more bytes of - commands and/or data. + Pepare the SPI interface for transmitting on or more bytes of + commands and/or data. */ - void MVSPIClass::packetBegin() { - // Enable SPI mode - SPCR |= _BV(SPE); +void MVSPIClass::packetBegin() { + // Enable SPI mode + SPCR |= _BV(SPE); - // Set SS low - SSLOW; + // Set SS low + SSLOW; } /** \brief End a SPI packet transmission - End a SPI packet transmission: - - Wait for the last byte to finish being transmitted. - - Set DC to command mode (even if already set that way, just in case). - - Set SS high. - - Disable SPI mode (causing SCK and MOSI to go low). + End a SPI packet transmission: + - Wait for the last byte to finish being transmitted. + - Set DC to command mode (even if already set that way, just in case). + - Set SS high. + - Disable SPI mode (causing SCK and MOSI to go low). */ - void MVSPIClass::packetEnd() { - while (!(SPSR & _BV(SPIF))) - ; - DCLOW; - SSHIGH; - SPCR &= ~_BV(SPE); +void MVSPIClass::packetEnd() { + while (!(SPSR & _BV(SPIF))) + ; + DCLOW; + SSHIGH; + SPCR &= ~_BV(SPE); } /** \brief Set SPI bit order. - Set SPI port bit order with LSBFIRST or MSBFIRST. + Set SPI port bit order with LSBFIRST or MSBFIRST. */ - void MVSPIClass::setBitOrder(uint8_t bitOrder) - { - if(bitOrder == LSBFIRST) { - SPCR |= _BV(DORD); - } else { - SPCR &= ~(_BV(DORD)); - } +void MVSPIClass::setBitOrder(uint8_t bitOrder) +{ + if(bitOrder == LSBFIRST) { + SPCR |= _BV(DORD); + } else { + SPCR &= ~(_BV(DORD)); } +} /** \brief Set SPI data mode. - Set the SPI data mode: clock polarity and phase. mode - SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3. + Set the SPI data mode: clock polarity and phase. mode - SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3. */ - void MVSPIClass::setDataMode(uint8_t mode) - { - SPCR = (SPCR & ~SPI_MODE_MASK) | mode; - } +void MVSPIClass::setDataMode(uint8_t mode) +{ + SPCR = (SPCR & ~SPI_MODE_MASK) | mode; +} /** \brief Set clock divider. - Set the clocl divider of the SPI, default is 4Mhz. + Set the clocl divider of the SPI, default is 4Mhz. - rate: SPI_CLOCK_DIV2 - SPI_CLOCK_DIV4 - SPI_CLOCK_DIV8 - SPI_CLOCK_DIV16 - SPI_CLOCK_DIV32 - SPI_CLOCK_DIV64 - SPI_CLOCK_DIV128 + rate: SPI_CLOCK_DIV2 + SPI_CLOCK_DIV4 + SPI_CLOCK_DIV8 + SPI_CLOCK_DIV16 + SPI_CLOCK_DIV32 + SPI_CLOCK_DIV64 + SPI_CLOCK_DIV128 */ - void MVSPIClass::setClockDivider(uint8_t rate) - { - SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK); - SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK); - } +void MVSPIClass::setClockDivider(uint8_t rate) +{ + SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK); + SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK); +} - MVSPIClass MVSPI; - MicroView uView; +MVSPIClass MVSPI; +MicroView uView; diff --git a/MicroView.h b/MicroView.h index e0ee151..9774311 100644 --- a/MicroView.h +++ b/MicroView.h @@ -226,6 +226,7 @@ private: class MicroViewWidget { public: + bool needToDrawPrev; MicroViewWidget(uint8_t newx, uint8_t newy, int16_t min, int16_t max); uint8_t getX(); uint8_t getY(); @@ -242,6 +243,8 @@ public: virtual void draw(){}; /** \brief Draw widget face overridden by child class. */ virtual void drawFace(){}; + /** \brief ReDraw widget overridden by child class. */ + virtual void reDraw(){}; private: uint8_t x; @@ -257,6 +260,7 @@ public: MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty); void draw(); void drawFace(); + void reDraw(); private: uint8_t totalTicks, style; bool needFirstDraw; @@ -269,6 +273,7 @@ public: MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty); void draw(); void drawFace(); + void reDraw(); private: uint8_t radius, style; bool needFirstDraw; @@ -339,6 +344,5 @@ void MVSPIClass::detachInterrupt() { SPCR &= ~_BV(SPIE); } - extern MicroView uView; #endif diff --git a/README.md b/README.md index c414f7a..f0f02f9 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ void loop() { void setup() { uView.begin(); uView.clear(PAGE); + Serial.begin(115200); // user decide the baud rate } void loop() { @@ -91,6 +92,10 @@ void loop() { ## History +**v1.17b: 4th August 2014 by JP Liew** +* added reDraw() for MicroViewWidget class +* removed Serial.begin() from uView.begin() so that user can have control + **v1.16b: 3rd August 2014 by czetie** * added vertical slider widget @@ -143,7 +148,7 @@ void loop() { **v1.05b: 6th February 2014 by JP Liew** * changed MICROVIEW class name to MicroView -* created MICROVIEWWIDGET class +* created MicroViewWidget class * added routines to draw widget * added slider widget * merged MicroViewWidget into MicroView