Craig Evans / N5110

Dependents:   LV7_LCDtest LV7_Grupa5_Tim003_Zadatak1 lv7_Grupa5_Tim008_zad1 LV7_PAI_Grupa5_tim10_Zadatak1 ... more

Files at this revision

API Documentation at this revision

Comitter:
eencae
Date:
Tue Mar 17 12:56:03 2015 +0000
Parent:
16:b37a3a260598
Child:
18:1af393359298
Commit message:
Added functions for drawing primitive shapes (lines, circles and rectangles). Can draw white, black and dotted lines. Can draw transparent (with outline), black fill and white fill circles and rectangles.

Changed in this revision

N5110.cpp Show annotated file Show diff for this revision Revisions of this file
N5110.h Show annotated file Show diff for this revision Revisions of this file
--- a/N5110.cpp	Tue Mar 10 19:33:55 2015 +0000
+++ b/N5110.cpp	Tue Mar 17 12:56:03 2015 +0000
@@ -139,7 +139,7 @@
 {
     int i;
     sce->write(0);  //set CE low to begin frame
-    for(i = 0; i < 504; i++) { // 48 x 84 bits = 504 bytes
+    for(i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes
         spi->write(0x00);  // send 0's
     }
     sce->write(1); // set CE high to end frame
@@ -149,18 +149,10 @@
 // function to set the XY address in RAM for subsequenct data write
 void N5110::setXYAddress(int x, int y)
 {
-    // check whether address is in range
-    if (x > 83)
-        x=83;
-    if (y > 5)
-        y=5;
-    if (x < 0)
-        x=0;
-    if (y < 0)
-        y=0;
-
-    sendCommand(0x80 | x);  // send addresses to display with relevant mask
-    sendCommand(0x40 | y);
+    if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
+        sendCommand(0x80 | x);  // send addresses to display with relevant mask
+        sendCommand(0x40 | y);
+    }
 }
 
 // These functions are used to set, clear and get the value of pixels in the display
@@ -168,21 +160,28 @@
 // function must be called after set and clear in order to update the display
 void N5110::setPixel(int x, int y)
 {
-    // calculate bank and shift 1 to required position in the data byte
-    buffer[x][y/8] |= (1 << y%8);
+    if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
+        // calculate bank and shift 1 to required position in the data byte
+        buffer[x][y/8] |= (1 << y%8);
+    }
 }
 
 void N5110::clearPixel(int x, int y)
 {
-    // calculate bank and shift 1 to required position (using bit clear)
-    buffer[x][y/8] &= ~(1 << y%8);
+    if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
+        // calculate bank and shift 1 to required position (using bit clear)
+        buffer[x][y/8] &= ~(1 << y%8);
+    }
 }
 
 int N5110::getPixel(int x, int y)
 {
-    // return relevant bank and mask required bit
-    return (int) buffer[x][y/8] & (1 << y%8);
-
+    if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
+        // return relevant bank and mask required bit
+        return (int) buffer[x][y/8] & (1 << y%8);
+    } else {
+        return 0;
+    }
 }
 
 // function to refresh the display
@@ -196,8 +195,8 @@
 
     sce->write(0);  //set CE low to begin frame
 
-    for(j = 0; j < 6; j++) {  // be careful to use correct order (j,i) for horizontal addressing
-        for(i = 0; i < 84; i++) {
+    for(j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
+        for(i = 0; i < WIDTH; i++) {
             spi->write(buffer[i][j]);  // send buffer
         }
     }
@@ -210,8 +209,8 @@
 void N5110::randomiseBuffer()
 {
     int i,j;
-    for(j = 0; j < 6; j++) {  // be careful to use correct order (j,i) for horizontal addressing
-        for(i = 0; i < 84; i++) {
+    for(j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
+        for(i = 0; i < WIDTH; i++) {
             buffer[i][j] = rand()%256;  // generate random byte
         }
     }
@@ -223,10 +222,10 @@
 {
     for (int i = 0; i < 5 ; i++ ) {
         buffer[x+i][y] = font5x7[(c - 32)*5 + i];
-         // array is offset by 32 relative to ASCII, each character is 5 pixels wide
+        // array is offset by 32 relative to ASCII, each character is 5 pixels wide
     }
-    
-     refresh();  // this sends the buffer to the display and sets address (cursor) back to 0,0
+
+    refresh();  // this sends the buffer to the display and sets address (cursor) back to 0,0
 }
 
 // function to print string at specified position
@@ -261,8 +260,8 @@
 void N5110::clearBuffer()
 {
     int i,j;
-    for (i=0; i<84; i++) {  // loop through the banks and set the buffer to 0
-        for (j=0; j<6; j++) {
+    for (i=0; i<WIDTH; i++) {  // loop through the banks and set the buffer to 0
+        for (j=0; j<BANKS; j++) {
             buffer[i][j]=0;
         }
     }
@@ -274,7 +273,7 @@
 
     int i;
 
-    for (i=0; i<84; i++) {  // loop through array
+    for (i=0; i<WIDTH; i++) {  // loop through array
         // elements are normalised from 0.0 to 1.0, so multiply
         // by 47 to convert to pixel range, and subtract from 47
         // since top-left is 0,0 in the display geometry
@@ -283,5 +282,113 @@
 
     refresh();
 
+}
 
-}
\ No newline at end of file
+// function to draw circle
+void N5110:: drawCircle(int x0,int y0,int radius,int fill)
+{
+    // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
+    int x = radius;
+    int y = 0;
+    int radiusError = 1-x;
+
+    while(x >= y) {
+
+        // if transparent, just draw outline
+        if (fill == 0) {
+            setPixel( x + x0,  y + y0);
+            setPixel(-x + x0,  y + y0);
+            setPixel( y + x0,  x + y0);
+            setPixel(-y + x0,  x + y0);
+            setPixel(-y + x0, -x + y0);
+            setPixel( y + x0, -x + y0);
+            setPixel( x + x0, -y + y0);
+            setPixel(-x + x0, -y + y0);
+        } else {  // drawing filled circle, so draw lines between points at same y value
+
+            int type = (fill==1) ? 1:0;  // black or white fill
+
+            drawLine(x+x0,y+y0,-x+x0,y+y0,type);
+            drawLine(y+x0,x+y0,-y+x0,x+y0,type);
+            drawLine(y+x0,-x+y0,-y+x0,-x+y0,type);
+            drawLine(x+x0,-y+y0,-x+x0,-y+y0,type);
+        }
+
+
+        y++;
+        if (radiusError<0) {
+            radiusError += 2 * y + 1;
+        } else {
+            x--;
+            radiusError += 2 * (y - x) + 1;
+        }
+    }
+
+    refresh();
+}
+
+void N5110::drawLine(int x0,int y0,int x1,int y1,int type)
+{
+    int y_range = y1-y0;  // calc range of y and x
+    int x_range = x1-x0;
+    int start,stop,step;
+
+    // if dotted line, set step to 2, else step is 1
+    step = (type==2) ? 2:1;
+
+    // make sure we loop over the largest range to get the most pixels on the display
+    // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
+    // or else we'll only end up with 1 pixel in the x column
+    if ( abs(x_range) > abs(y_range) ) {
+
+        // ensure we loop from smallest to largest or else for-loop won't run as expected
+        start = x1>x0 ? x0:x1;
+        stop =  x1>x0 ? x1:x0;
+
+        // loop between x pixels
+        for (int x = start; x<= stop ; x+=step) {
+            // do linear interpolation
+            int y = y0 + (y1-y0)*(x-x0)/(x1-x0);
+
+            if (type == 0)   // if 'white' line, turn off pixel
+                clearPixel(x,y);
+            else
+                setPixel(x,y);  // else if 'black' or 'dotted' turn on pixel
+        }
+    } else {
+
+        // ensure we loop from smallest to largest or else for-loop won't run as expected
+        start = y1>y0 ? y0:y1;
+        stop =  y1>y0 ? y1:y0;
+
+        for (int y = start; y<= stop ; y+=step) {
+            // do linear interpolation
+            int x = x0 + (x1-x0)*(y-y0)/(y1-y0);
+
+            if (type == 0)   // if 'white' line, turn off pixel
+                clearPixel(x,y);
+            else
+                setPixel(x,y);  // else if 'black' or 'dotted' turn on pixel
+
+        }
+    }
+
+    refresh();
+}
+
+void N5110::drawRect(int x0,int y0,int width,int height,int fill)
+{
+
+    if (fill == 0) { // transparent, just outline
+        drawLine(x0,y0,x0+width,y0,1);  // top
+        drawLine(x0,y0+height,x0+width,y0+height,1);  // bottom
+        drawLine(x0,y0,x0,y0+height,1);  // left
+        drawLine(x0+width,y0,x0+width,y0+height,1);  // right
+    } else { // filled rectangle
+        int type = (fill==1) ? 1:0;  // black or white fill
+        for (int y = y0; y<= y0+height; y++) {  // loop through rows of rectangle
+            drawLine(x0,y,x0+width,y,type);  // draw line across screen
+        }
+    }
+
+}
--- a/N5110.h	Tue Mar 10 19:33:55 2015 +0000
+++ b/N5110.h	Tue Mar 17 12:56:03 2015 +0000
@@ -32,35 +32,36 @@
 #define CMD_VOP_6V06           0xB2
 #define CMD_VOP_7V38           0xC8
 
-// number of pixels on display  
+// number of pixels on display
 #define WIDTH 84
 #define HEIGHT 48
+#define BANKS 6
 
 #include "mbed.h"
 
-/** 
+/**
 @brief Library for interfacing with Nokia 5110 LCD display (https://www.sparkfun.com/products/10168) using the hardware SPI on the mbed.
 @brief The display is powered from a GPIO pin meaning it can be controlled via software.  The LED backlight is also software-controllable (via PWM pin).
-@brief Can print characters and strings to the display using the included 5x7 font.  
+@brief Can print characters and strings to the display using the included 5x7 font.
 @brief The library also implements a screen buffer so that individual pixels on the display (84 x 48) can be set, cleared and read.
-
+@brief The library can print primitive shapes (lines, circles, rectangles)
 @brief Acknowledgements to Chris Yan's Nokia_5110 Library.
 
-@brief Revision 1.1
+@brief Revision 1.2
 
 @author Craig A. Evans
-@date   March 2015
+@date   17th March 2015
  *
  * Example:
  * @code
- 
+
 #include "mbed.h"
 #include "N5110.h"
 
 //    VCC,SCE,RST,D/C,MOSI,SCLK,LED
 N5110 lcd(p7,p8,p9,p10,p11,p13,p21);
 // Can also power (VCC) directly from VOUT (3.3 V) -
-// Can give better performance due to current limitation from GPIO pin 
+// Can give better performance due to current limitation from GPIO pin
 
 int main()
 {
@@ -69,63 +70,88 @@
 
     while(1) {
 
-        char buffer[14];  // each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
-        // so can display a string of a maximum 14 characters in length
-        
-        lcd.clear();            // clear display
         // these are default settings so not strictly needed
         lcd.normalMode();      // normal colour mode
-        lcd.setBrightness(0.5); // put LED backlight on full
-        
+        lcd.setBrightness(0.5); // put LED backlight on 50%
+
         // can directly print strings at specified co-ordinates
         lcd.printString("Hello, World!",0,0);
 
+        char buffer[14];  // each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
+        // so can display a string of a maximum 14 characters in length
         // or create formatted strings - ensure they aren't more than 14 characters long
         int temperature = 27;
         int length = sprintf(buffer,"T = %2d C",temperature); // print formatted data to buffer
         // it is important the format specifier ensures the length will fit in the buffer
         if (length <= 14)  // if string will fit on display
             lcd.printString(buffer,0,1);           // display on screen
-       
+
         float pressure = 1012.3;  // same idea with floats
         length = sprintf(buffer,"P = %.2f mb",pressure);
         if (length <= 14)
             lcd.printString(buffer,0,2);
-    
-        // can also print individual characters
+
+        // can also print individual characters at specified place
         lcd.printChar('X',5,3);
-        
-         // draw a line across the display at y = 40 pixels (origin top-left)
+
+        // draw a line across the display at y = 40 pixels (origin top-left)
         for (int i = 0; i < WIDTH; i++) {
-            lcd.setPixel(i,40);    
+            lcd.setPixel(i,40);
         }
         // need to refresh display after setting pixels
-        lcd.refresh(); 
-        
+        lcd.refresh();
+
         // can also check status of pixels using getPixel(x,y)
-         
+
         wait(5.0);
-        
         lcd.clear();            // clear display
         lcd.inverseMode();      // invert colours
         lcd.setBrightness(1.0); // put LED backlight on full
-    
+
         float array[84];
-        
+
         for (int i = 0; i < 84; i++) {
-            array[i] = 0.5 + 0.5*sin(i*2*3.14/84);    
+            array[i] = 0.5 + 0.5*sin(i*2*3.14/84);
         }
-        
+
         // can also plot graphs - 84 elements only
         // values must be in range 0.0 - 1.0
         lcd.plotArray(array);
-        
-        wait(5.0); 
+        wait(5.0);
+        lcd.clear();
+        lcd.normalMode();      // normal colour mode back
+        lcd.setBrightness(0.5); // put LED backlight on 50%
+
+        // example of drawing lines
+        for (int x = 0; x < WIDTH ; x+=10) {
+            // x0,y0,x1,y1,type 0-white,1-black,2-dotted
+            lcd.drawLine(0,0,x,HEIGHT,2);
+        }
+
+        wait(5.0);
+        lcd.clear();
+
+        // example of how to draw circles
+        lcd.drawCircle(WIDTH/2,HEIGHT/2,20,1);  // x,y,radius,black fill
+        lcd.drawCircle(WIDTH/2,HEIGHT/2,10,2);  // x,y,radius,white fill
+        lcd.drawCircle(WIDTH/2,HEIGHT/2,30,0);  // x,y,radius,transparent with outline
+
+        wait(5.0);
+        lcd.clear();
+
+        // example of how to draw rectangles
+        //          origin x,y,width,height,type
+        lcd.drawRect(10,10,50,30,1);  // filled black rectangle
+        lcd.drawRect(15,15,20,10,2);  // filled white rectange (no outline)
+        lcd.drawRect(2,2,70,40,0);    // transparent, just outline
+
+         wait(5.0);
+        lcd.clear();
 
     }
 }
 
-  
+
  * @endcode
  */
 class N5110
@@ -140,56 +166,56 @@
     * @param dc  Pin connected to data/command select (pin 5)
     * @param mosi Pin connected to data input (MOSI) (pin 6)
     * @param sclk Pin connected to serial clock (SCLK) (pin 7)
-    * @param led Pin connected to LED backlight (must be PWM) (pin 8) 
-    * 
+    * @param led Pin connected to LED backlight (must be PWM) (pin 8)
+    *
     */
     N5110(PinName pwrPin, PinName scePin, PinName rstPin, PinName dcPin, PinName mosiPin, PinName sclkPin, PinName ledPin);
-    
+
     /** Initialise display
     *
     *   Powers up the display and turns on backlight (50% brightness default).
     *   Sets the display up in horizontal addressing mode and with normal video mode.
     */
     void init();
-    
+
     /** Turn off
     *
     *   Powers down the display and turns of the backlight.
     *   Needs to be reinitialised before being re-used.
     */
     void turnOff();
-    
+
     /** Clears
     *
     *   Clears the screen.
     */
     void clear();
-    
+
     /** Turn on normal video mode (default)
     *  Black on white
     */
     void normalMode();
-    
+
     /** Turn on inverse video mode (default)
     *  White on black
     */
     void inverseMode();
-    
+
     /** Set Brightness
     *
     *   Sets brightness of LED backlight.
     *   @param brightness - float in range 0.0 to 1.0
     */
     void setBrightness(float brightness);
-    
+
     /** Print String
     *
-    *   Prints a string of characters to the display.  
+    *   Prints a string of characters to the display.
     *   @param x - the column number (0 to 83)
     *   @param y - the row number (0 to 5) - the display is split into 6 banks - each bank can be considered a row
     */
     void printString(const char * str,int x,int y);
-    
+
     /** Print Character
     *
     *   Sends a character to the display.  Printed at the specified location
@@ -198,60 +224,93 @@
     *   @param y - the row number (0 to 5) - the display is split into 6 banks - each bank can be considered a row
     */
     void printChar(char c,int x,int y);
-    
+
     /** Set a Pixel
     *
     *   This function sets a pixel in the display. A call to refresh() must be made
     *   to update the display to reflect the change in pixels.
     *   @param  x - the x co-ordinate of the pixel (0 to 83)
-    *   @param  y - the y co-ordinate of the pixel (0 to 47) 
+    *   @param  y - the y co-ordinate of the pixel (0 to 47)
     */
     void setPixel(int x, int y);
-    
+
     /** Clear a Pixel
     *
     *   This function clears pixel in the display. A call to refresh() must be made
     *   to update the display to reflect the change in pixels.
     *   @param  x - the x co-ordinate of the pixel (0 to 83)
-    *   @param  y - the y co-ordinate of the pixel (0 to 47) 
+    *   @param  y - the y co-ordinate of the pixel (0 to 47)
     */
     void clearPixel(int x, int y);
-    
+
     /** Get a Pixel
     *
     *   This function gets the status of a pixel in the display.
     *   @param  x - the x co-ordinate of the pixel (0 to 83)
-    *   @param  y - the y co-ordinate of the pixel (0 to 47) 
-    *   @returns 
+    *   @param  y - the y co-ordinate of the pixel (0 to 47)
+    *   @returns
     *       0           - pixel is clear
     *       non-zero    - pixel is set
     */
     int getPixel(int x, int y);
-    
+
     /** Refresh display
     *
     *   This functions refreshes the display to reflect the current data in the buffer.
-    */    
+    */
     void refresh();
-    
+
     /** Randomise buffer
     *
-    *   This function fills the buffer with random data.  Can be used to test the display.  
+    *   This function fills the buffer with random data.  Can be used to test the display.
     *   A call to refresh() must be made to update the display to reflect the change in pixels.
     *   The seed is not set and so the generated pattern will probably be the same each time.
     *   TODO: Randomise the seed - maybe using the noise on the AnalogIn pins.
     */
     void randomiseBuffer();
-    
+
     /** Plot Array
     *
-    *   This function plots a one-dimensional array on the display. The values in the array
-    *   correspond to the y values of the plot and these are plotted along the x-axis (one
-    *   value per pixel along the x-axis of the display. This means only the first 84 values are 
-    *   plotted. y values in the array should be normalised in the range 0.0 to 1.0. 
+    *   This function plots a one-dimensional array on the display.
+    *   @param array[] - y values of the plot. Values should be normalised in the range 0.0 to 1.0. First 84 plotted.
     */
     void plotArray(float array[]);
 
+    /** Draw Circle
+    *
+    *   This function draws a circle at the specified origin with specified radius to the display.
+    *   Uses the midpoint circle algorithm.
+    *   @see http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
+    *   @param  x0 - x-coordinate of centre
+    *   @param  y0 - y-coordinate of centre
+    *   @param  radius - radius of circle in pixels
+    *   @param  fill - 0 transparent (w/outline), 1 filled black, 2 filled white (wo/outline)
+    */
+    void drawCircle(int x0,int y0,int radius,int fill);
+
+    /** Draw Line
+    *
+    *   This function draws a line between the specified points using linear interpolation.
+    *   @param  x0 - x-coordinate of first point
+    *   @param  y0 - y-coordinate of first point
+    *   @param  x1 - x-coordinate of last point
+    *   @param  y1 - y-coordinate of last point
+    *   @param  type - 0 white,1 black,2 dotted
+    */
+    void drawLine(int x0,int y0,int x1,int y1,int type);
+
+    /** Draw Rectangle
+    *
+    *   This function draws a rectangle.
+    *   @param  x0 - x-coordinate of origin (top-left)
+    *   @param  y0 - y-coordinate of origin (top-left)
+    *   @param  width - width of rectangle
+    *   @param  height - height of rectangle
+    *   @param  fill - 0 transparent (w/outline), 1 filled black, 2 filled white (wo/outline)
+    */
+    void drawRect(int x0,int y0,int width,int height,int fill);
+
+
 private:
 
     void setXYAddress(int x, int y);