Newhaven 320x240 LCD

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
pbevans89
Date:
Mon Feb 28 17:48:12 2011 +0000
Parent:
3:1cf3ec6c70d7
Commit message:

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
newhaven.cpp Show annotated file Show diff for this revision Revisions of this file
newhaven.h Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Sun Feb 27 23:30:14 2011 +0000
+++ b/main.cpp	Mon Feb 28 17:48:12 2011 +0000
@@ -1,3 +1,7 @@
+/* mbed Newhaven LCD simple Pong demonstration
+ * Copywrite (c) 2011, Paul Evans
+ */
+
 #include "mbed.h"
 #include "newhaven.h"
 
@@ -5,19 +9,42 @@
 NHLCD   MyLCD(p5,p6,p7,p16,p17,&MyBus);
 
 int main() {
-    int i;
+    int r1 = 100, r2 = 100, rb = 115, cb = 155;
+    int dr = 5, dc = 5;
+
     MyLCD.Init();
     MyLCD.clearScreen();
     wait(.5);
+    MyLCD.text("PONG!", 0, 15);
+        
     while(1)
     {
-        MyLCD.text("Hello World!", 10, 1);
-        wait(1);
-        for(i = 0; i < 20; i++){
-            MyLCD.setPixel(i,i);
+        MyLCD.fillRect(r1, 0, 20, 4, 1);    // draw the paddles and ball
+        MyLCD.fillRect(r2, 312, 20, 4, 1);
+        MyLCD.fillRect(rb, cb, 3, 3, 1);
+        
+        wait(.2);                           // wait between frames                            
+        
+        MyLCD.fillRect(r1, 0, 20, 4, 0);    // clear the paddles and balls
+        MyLCD.fillRect(r2, 312, 20, 4, 0);
+        MyLCD.fillRect(rb, cb, 4, 4, 0);
+        
+        rb += dr;   // move the ball
+        cb += dc;
+        if (cb > 100) { // move the right paddle if necessary
+            if (r2 > rb && r2 > 0) r2-=5;
+            else if (r2 < 214) r2+=5;
         }
-        wait(1);
-        MyLCD.clearScreen();
-        wait(1);
+        if (cb < 220) { // move the left paddle if necessary
+            if (r1 > rb && r1 > 0) r1-=5;
+            else if (r1 < 214) r1+=5;
+        }
+        if (cb > 310 || cb < 4){    // check bounds for ball column
+            dc = -dc;
+            cb += dc;
+        }if (rb < 10 || rb > 234){  // check bounds for ball row
+            dr = -dr;
+            rb += dr;
+        }
     }
 }
--- a/newhaven.cpp	Sun Feb 27 23:30:14 2011 +0000
+++ b/newhaven.cpp	Mon Feb 28 17:48:12 2011 +0000
@@ -21,6 +21,12 @@
     while(i--);
 }
 
+void swap(int* a, int* b){
+    int temp = *a;
+    *a = *b;
+    *b = temp;
+}
+
 // send commands to the LCD
 void NHLCD::comm_out(unsigned char j){
     LCD_PORT->output();     // sets the buffer to output data
@@ -29,7 +35,7 @@
     CS = 0;                 // active LOW chip select
     RW = 0;                 // set to 0 for write operation
     E = 1;                  // operation enable
-    delay(1);               // wait for operation to complete
+    //delay(1);               // wait for operation to complete
     E = 0;                  // reset values
     RW = 1;
     CS = 1; 
@@ -43,7 +49,7 @@
     CS = 0;                 // active LOW chip select
     RW = 0;                 // set to 0 for write operation
     E = 1;                  // operation enable
-    delay(1);               // wait for operation to complete
+    //delay(1);               // wait for operation to complete
     E = 0;                  // reset values           
     RW = 1;
     CS = 1;
@@ -84,31 +90,59 @@
 /* set an individual pixel on the screen.
  * pixels are grouped in bytes, so you must isolate a particular pixel.
  */
-void NHLCD::setPixel(int row, int col){
-    int loc = (0x04<<8)|(0xB0);                 //sets location to the top left corner of drawing screen
-    int c = loc+row*40+(col/8);                 // gets address of the correct byte
-    comm_out(0x46);                             // command to set cursor location
-    data_out((unsigned char)(c&0xFF));          // lower 8 bits of address
-    data_out((unsigned char)((c&0xFF00)>>8));   // upper 8 bits of address
-    comm_out(0x43);                             // command to read the byte
-    LCD_PORT->input();                          // sets the buffer to input data
-    unsigned char buffer = LCD_PORT->read();    // stores byte in buffer
-    buffer = buffer|(1<<(7-((row*320+col)%8))); // sets the particular pixel on the byte
-    LCD_PORT->output();                         // sets the buffer to output data
-    
-    comm_out(0x46);                             //command to set cursor location
-    data_out((unsigned char)(c&0xFF));          // lower 8 bits of address
-    data_out((unsigned char)((c&0xFF00)>>8));   // upper 8 bits of address
-    comm_out(0x42);                             // command to write to the screen
-    data_out(buffer);                           // write buffer to the screen
+void NHLCD::setPixel(int row, int col, int color){
+    int c = row*40+(col/8);                         // get location in buffer
+    char x = 1<<(7-(col%8));                        // sets the bit to alter
+    if (color)                                      // to mark the bit
+        screenBuffer[c] |= x;                       // marks the bit
+    else                                            // to clear the bit
+        screenBuffer[c] &= ~x;                      // clears the bit
+    LCD_PORT->output();                             // sets the buffer to output data
+    int loc = c+0x4B0;                              // get location on drawing screen
+    comm_out(0x46);                                 // command to set cursor location
+    data_out((unsigned char)(loc&0xFF));            // lower 8 bits of address
+    data_out((unsigned char)((loc&0xFF00)>>8));     // upper 8 bits of address
+    comm_out(0x42);                                 // command to write data
+    data_out(screenBuffer[c]);                      // write byte to the screen
+}
+
+// draw a line -- Bresenham's line algorithm
+void NHLCD::drawLine(int r1, int c1, int r2, int c2, int color){
+    int w = r2 - r1;                            // calculate width of line
+    int h = c2 - c1;                            // calculate height of line
+    double ratio;
+    int x, y;
+    int upright = 0;                            // assumes the line is "wide"
+    if (abs(h) > abs(w)) {                      // checks if height is greater than width
+        upright = 1;                            // if it is, the line is "tall"            
+        swap(&c1, &r1);                         // mirrors coordinates over the line y=x to make it "wide"            
+        swap(&c2, &r2);
+        swap(&w, &h);
+    }
+    if (r1 > r2) {                              // if the first row is on the right, swaps start and end coordinates
+        swap(&c1, &c2);                         // now the line is always drawn from "bottom-left" to "top-right"
+        swap(&r1, &r2);
+    }
+    ratio = ((double) h) / w;                   // calculates ratio of height to width
+    for (x = r1; x < r2; x++) {                 // iterates through the rows
+        y = c1 + (x - r1) * ratio;              // calculates the height at this particular row
+        if (upright) setPixel(y, x, color);     // depending on if the line is "wide" or "tall", you have to 
+        else setPixel(x, y, color);             //      call setPixel differently
+    }
+}
+
+// draw and fill a rectangle
+void NHLCD::fillRect(int row, int col, int height, int width, int color){
+    for (int r = 0; r < height; r++)        // iterate through each row
+        for (int c = 0; c < width; c++)     // iterate through each column
+            setPixel(row+r,col+c,color);    // set each pixel in the rectangle
 }
 
 // initialize the LCD
 void NHLCD::Init(void){
-    /* reset the device */
-    RST = 0;
+    RST = 0;        // resets the device
     delay(5);
-    RST = 1;
+    RST = 1;        // restarts it
     delay(10);
     
     comm_out(0x40); // system set command
@@ -117,7 +151,7 @@
     data_out(0x87); // horizontal character size (0x80 = 1) MUST BE MULTIPLE OF 320
     data_out(0x07); // vertical character size (0x00 = 1)  MUST BE MULTIPLE OF 240
     data_out(40);   // addresses per line
-    data_out(80);   // bytes per line
+    data_out(80);   // words per line
     data_out(0xEF); // 240 displace lines
     data_out(0x28); // virtual address 1
     data_out(0x00); // virtual address 2
@@ -151,5 +185,7 @@
     
     comm_out(0x59); // disp on/off
     data_out(0x16); // on
-    wait_ms(5);
+    
+    for(int i = 0; i < 40*240; i++)
+        screenBuffer[i] = 0;
 }
--- a/newhaven.h	Sun Feb 27 23:30:14 2011 +0000
+++ b/newhaven.h	Mon Feb 28 17:48:12 2011 +0000
@@ -67,14 +67,37 @@
          *
          * @param row the row of the pixel
          * @param col the column of the pixel
+         * @param color 1 = on, 0 = off
          */
-        void setPixel(int row, int col);
+        void setPixel(int row, int col, int color);
+        
+        /* draws a line on the LCD
+         *
+         * @param r1 the row of the first endpoint
+         * @param c1 the column of the first endpoint
+         * @param r2 the row of the second endpoint
+         * @param c2 the column of the second endpoint
+         * @param color 1 = on, 0 = off
+         */
+        void drawLine(int r1, int c1, int r2, int c2, int color);
+        
+        /* draws and fills a rectangle on the LCD
+         *
+         * @param row the row of the top-left pixel
+         * @param col the column of the top-left pixel
+         * @param width the width of the rectangle
+         * @param height the height of the rectangle
+         * @param color 1 = on, 0 = off
+         */
+        void fillRect(int row, int col, int width, int height, int color);
         
     private:
         DigitalOut E,RW,A0,CS,RST;   
-        BusInOut *LCD_PORT;   
+        BusInOut *LCD_PORT;
+        unsigned char screenBuffer[240*40];   
         
 };
 
 void delay(unsigned int n);
 void delay1(unsigned int n);
+void swap(int* a, int* b);