Newhaven 320x240 LCD

Dependencies:   mbed

newhaven.cpp

Committer:
pbevans89
Date:
2011-02-28
Revision:
4:aa6dc362b462
Parent:
3:1cf3ec6c70d7

File content as of revision 4:aa6dc362b462:

/* mbed Newhaven LCD Library
 * Copywrite (c) 2011, Paul Evans
 */

#include "mbed.h"
#include "newhaven.h"

NHLCD::NHLCD(PinName PIN_E,PinName PIN_RW,PinName PIN_A0,PinName PIN_CS,PinName PIN_RST, BusInOut *BUSLCD)
    : E(PIN_E),RW(PIN_RW),A0(PIN_A0),CS(PIN_CS),RST(PIN_RST){
    LCD_PORT = BUSLCD;   
}

void delay(unsigned int n){
    unsigned int i,j;
    for (i=0;i<n;i++)
          for (j=0;j<350;j++)
              {;}
}

void delay1(unsigned int i){
    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
    A0 = 1;                 // set for a command output
    LCD_PORT->write(j);     // send the data in the buffer
    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
    E = 0;                  // reset values
    RW = 1;
    CS = 1; 
}

// send data to the LCD
void NHLCD::data_out(unsigned char j){
    LCD_PORT->output();     // sets the buffer to output data
    A0 = 0;                 // set for a data output
    LCD_PORT->write(j);     // send the data in the buffer
    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
    E = 0;                  // reset values           
    RW = 1;
    CS = 1;
}

// clears the entire screen
void NHLCD::clearScreen(){
    int n;
    comm_out(0x46);         // command to set cursor location
    data_out(0x00);         // 0x00 is the start of text screen
    data_out(0x00);
    comm_out(0x42);         // command to write data
    for(n=0;n<1200;n++){    // 1200 locations on the screen
        data_out(0x20);     // fill each with a blank
    }
    comm_out(0x46);         // command to set cursor location
    data_out(0xB0);         // 0x4B0 is the start of drawing screen
    data_out(0x04);
    comm_out(0x42);         // command to write data
    for(n=0;n<9600;n++){    // 9600 total byte locations
        data_out(0x00);     // set each to 0
    }
}

// write text on the screen
void NHLCD::text(char *text, char row, char col){
    int c = row*40+col;                         // gets the correct address for the cursor
    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 data to screen
    while(*text != 0) {                         // write until you hit a null terminator
        data_out(*text);                        // write the current character to the screen
        text++;                                 // move to the next character
    }
}

/* 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 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){
    RST = 0;        // resets the device
    delay(5);
    RST = 1;        // restarts it
    delay(10);
    
    comm_out(0x40); // system set command
    delay(5);
    data_out(0x30); // parameters
    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);   // words per line
    data_out(0xEF); // 240 displace lines
    data_out(0x28); // virtual address 1
    data_out(0x00); // virtual address 2
    
    comm_out(0x44); // scroll
    data_out(0x00); // start address 1
    data_out(0x00); // start address 2
    data_out(0xEF); // 240 lines
    data_out(0xB0); // 2nd screen start1
    data_out(0x04); // 2nd screen start2
    data_out(0xEF); // 2nd screen 240 lines
    data_out(0x00); // 3rd screen address1
    data_out(0x00); // 3rd screen address2
    data_out(0x00); // 4th screen address1
    data_out(0x00); // 4th screen address2
    
    comm_out(0x5A); // hdot scr
    data_out(0x00); // horizontal pixel shift = 0
    
    comm_out(0x5B); // overlay
    data_out(0x00); // OR
    
    comm_out(0x58); // set display
    data_out(0x56); 
    
    comm_out(0x5D); // cursor form
    data_out(0x04); // 5 pixels wide
    data_out(0x86); // 7 pixels tall
    
    comm_out(0x4C); // cursor direction = right
    
    comm_out(0x59); // disp on/off
    data_out(0x16); // on
    
    for(int i = 0; i < 40*240; i++)
        screenBuffer[i] = 0;
}