Baseline for testing

LCD.cpp

Committer:
foxbrianr
Date:
2019-09-17
Revision:
2:73721d9e0056
Parent:
1:0f1dffc6103a

File content as of revision 2:73721d9e0056:

/**************************************************************************
 * @file     LCD.cpp
 * @brief    Base class for wrapping the interface with the New Haven 40x4
 *           LCD monitor. 
 * @version: V1.0
 * @date:    9/17/2019

 *
 * @note
 * Copyright (C) 2019 E3 Design. All rights reserved.
 *
 * @par
 * E3 Designers LLC is supplying this software for use with Cortex-M3 LPC1768
 * processor based microcontroller for the ESCM 2000 Monitor and Display.  
 *  *
 * @par
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 ******************************************************************************/
#include "mbed.h"
#include "LCD.h"
#include <stdio.h>
#include <ctype.h>


#define WAIT_TIME 100

#define wait_ms(x) ThisThread::sleep_for(x)

/*****************************************************************************/
LCD::LCD(): 
    LCD_E1(p17),
    LCD_E2(p18),
    LCD_RS(p19),
    LCD_RW(p20),
    //LCD_D4(p24),
    //LCD_D5(p23),
    //LCD_D6(p22),
    //LCD_D7(p21),
    //bus constructor is the reverse order of the pins in the byte order. 
    // d0 - d7
    LCD_DATA( p24, p23, p22, p21)
{
    
    
    LCD_DATA.output();
    LCD_DATA.mode(OpenDrain);
    LCD_E1.mode(OpenDrain);
    LCD_E2.mode(OpenDrain);
    LCD_RS.mode(OpenDrain);
    LCD_RW.mode(OpenDrain);
    isOutput=1;
    
}

/*****************************************************************************/
LCD::~LCD()
{
}



/*****************************************************************************/
void LCD::command1(char i) //Top half of the display 
{
   LCD_DATA.output();
   LCD_DATA = i;
   LCD_RW = 0;
   LCD_RS = 0;
   LCD_E1 = 1;
   wait_us(40); // wait 40 us for most commands
   LCD_E1 = 0;
   
   //printf("C1:%x\n\r", i);
}

/*****************************************************************************/
void LCD::command2(char i) //Bottom half of the display 
{
   LCD_DATA.output();
   LCD_DATA = i;
   LCD_RW = 0;
   LCD_RS = 0;
   LCD_E2 = 1;
   wait_us(40); // wait 40 us for most commands
   LCD_E2 = 0;
   
   //printf("C2:%x\n\r", i);
}

/*****************************************************************************/
void LCD::writedata1(char i) //Top half of the display 
{;
   LCD_DATA.output();
   LCD_DATA = i;
   LCD_RW = 0;
   LCD_RS = 1;
   LCD_E1 = 1;
   wait_us(40); // wait 40 us for most commands
   LCD_E1 = 0;
}

/*****************************************************************************/
void LCD::writedata2(char i) //Bottom half of the display 
{
   LCD_DATA.output();
   LCD_DATA = i;
   LCD_RW = 0;
   LCD_RS = 1;
   LCD_E2 = 1;
   wait_us(40); // wait 40 us for most commands
   LCD_E2 = 0;
}

/*****************************************************************************/
void LCD::nextline1(){
    writeCommand(0xc0,1,0);         //set DDRAM address to 40 (line 2)
}

/*****************************************************************************/
void LCD::nextline2(){
    writeCommand(0xc0,0,1);         //set DDRAM address to 40 (line 4)
}

/*****************************************************************************/
void LCD::display(char *show){  //show character data on display
    char datum;
    int i;
    for (i=0;i<40;i++){
        datum=*show;            //point to 1st line data
        writeData(datum,1,0);          //write to 1st line
        ++show;                 //next letter
    }
    nextline1();                //move address to line 2
    for (i=0;i<40;i++){
        datum=*show;
        writeData(datum,1,0);          //write to 2nd line
        ++show;
    }    
    for (i=0;i<40;i++){
        datum=*show;
        writeData(datum,0,1);          //write to 3rd line
        ++show;
    }
    nextline2();                //move address to line 4
    for (i=0;i<40;i++){
        datum=*show;
        writeData(datum,0,1);          //write to 4th line
        ++show;
    }
}


/*****************************************************************************/
void LCD::writeByte1(int value) {
    
    // -------------------------------------------------
    LCD_DATA.output();
    LCD_DATA = value >> 4;
    
    LCD_RW = 0;
    LCD_E1 = 1;
    wait_ms(2); // wait 40 us for most commands
    __nop();
    LCD_E1 = 0;
    
    // -------------------------------------------------
    wait_ms(1); // wait 40 us for most commands
    
    // -------------------------------------------------
    LCD_DATA = value >> 0;
    LCD_E1 = 1;
    wait_ms(2); // wait 40 us for most commands
    __nop();
    LCD_E1 = 0;
    
    //printf("x1:%x\n\r", value);
}

/*****************************************************************************/
void LCD::writeByte2(int value) {
    
    // -------------------------------------------------
    LCD_DATA.output();
    LCD_DATA = value >> 4;
    LCD_RW = 0;
    LCD_E2 = 1;
    wait_ms(2); // wait 40 us for most commands
    __nop();
    LCD_E2 = 0;
    
    // -------------------------------------------------
    wait_ms(1); // wait 40 us for most commands
    
    // -------------------------------------------------
    LCD_DATA = value >> 0;
    LCD_E2 = 1;
    wait_ms(2); // wait 40 us for most commands
    __nop();
    LCD_E2 = 0;
    
   //printf("x2:%x\n\r", value);
}

/************************************************************************/
void LCD::init(void)
{
    wait_ms(100);

    LCD_E1 = 0;
    LCD_E2 = 0;

    for (int i=0; i<3; i++) {
        command1(0x3);//Wake up
        command2(0x3);
        wait_ms(1); // wait 40 us for most commands
    }
    command1(0x2);// Set 4 bit mode
    command2(0x2);
    wait_ms(1); // wait 40 us for most commands


    LCD_RW = 0;
    LCD_RS = 0;

    writeCommand(0x2C,1,1); //Turn on display

    writeCommand(LCD_setDisplayOff,1,1); //Turn on display
    //writeCommand2(LCD_setDisplayOff);

    writeCommand(LCD_clearDisplay,1,1); //Clear display
    //writeCommand2(LCD_clearDisplay);

    writeCommand(LCD_entryModeSet,1,1); //Entry mode cursor increment
    //writeCommand2(LCD_entryModeSet);

    writeCommand(LCD_setDisplayOn,1,1); //Turn on display; no cursor
    //writeCommand2(LCD_setDisplayOn);


    LCD_E1 = 0;
    LCD_E2 = 0;

}

/*****************************************************************************/
void LCD::locate(int row, int column) {
    _row = row;
    _column = column;
}

/*****************************************************************************/
void LCD::cls(){
    
    clear(1,1);
    wait_ms(2);
    
    //fprintf(stdout,"C1:\n\r");
}
/*****************************************************************************/
void LCD::clear()
{
    locate(0,0);write("                                        ");
    locate(1,0);write("                                        ");
    locate(2,0);write("                                        ");
    locate(3,0);write("                                        ");
}
/*****************************************************************************/
void LCD::clear(int e1, int e2 ){

    waitBusy();
    writeCommand(LCD_clearDisplay,e1,e2);
    _row = 0;
    _column = 0;

}

/*****************************************************************************/
int LCD::isBusy1(void)
{
    volatile int input  = 0;
    volatile int hi  = 0;
    volatile int lo  = 0;
    int result = 0;
    
    LCD_RW = 1;
    __nop();
    LCD_RS = 0;
    
    LCD_DATA.input();      // switch port back to output 
    
    LCD_E1 = 1;
    __nop();
    lo = LCD_DATA.read() ;  // read low bit      
    LCD_E1 = 0;
    wait_ms(1);
    LCD_E1 = 1;
    hi = LCD_DATA.read() ;    // read high bit     
    __nop();
    LCD_E1 = 0;
           
        
    if ((0x8 & lo))  // wait until display is ready
    {
        result = 1;
    }
    result =0;
    LCD_RW = 0;
    LCD_DATA.output();      // switch port back to output 
    
    //fprintf(stdout,"isBusy1? = 0x%02x 0x%02x \n\r", lo,hi );  
    
    return result;
}

/*****************************************************************************/
int LCD::isBusy2(void) 
{
    
    volatile int input  = 0;
    volatile int hi  = 0;
    volatile int lo  = 0;
    int result = 0;
    
    LCD_RW = 1;
    __nop();
    LCD_RS = 0;

    LCD_DATA.input();      // switch port back to output 
    LCD_E2 = 1;
    __nop();
    lo = LCD_DATA.read()  >> 0;  // read low bit      
    LCD_E2 = 0;
    __nop();
    LCD_E2 = 1;
    hi = LCD_DATA.read() >> 4;    // read high bit     
    __nop();
    LCD_E2 = 0;
        
    
    if ((0x8 & lo))  // wait until display is ready
    {
        result = 1;
    }
    
    LCD_RW = 0;
    LCD_DATA.output();      // switch port back to output 
    
    //fprintf(stdout,"isBusy2? = 0x%02x 0x%02x \n\r", lo,hi );     
    return result;
}

/*****************************************************************************/
int LCD::isBusy(int e1, int e2)
{
    int input  = 0;
    int result = 0;
    
    if (e1) {
        result=isBusy1();
    }
        
    if (e2 && result==0) {
        
        result=isBusy2();
    }    
    
    return result;
}
        
/*****************************************************************************/
void LCD::waitBusy()
{     
    unsigned char statusBit;
    statusBit = isBusy(1,1);     
    //int i=0;
    while (statusBit)
    {
        fprintf(stdout,"!");
        statusBit = isBusy(1,1);     
        wait_us(1);
    } 
}

/*****************************************************************************/
void LCD::writeData(char value, int e1, int e2 ){
    
    
    int hi=( value & 0xF0 ) >> 4;
    int lo=( value & 0x0F ) >> 0;
    
    LCD_DATA.output();
        
    if(e1) {
                
        LCD_DATA  = hi;
        LCD_E1 = 1;
        wait_us(WAIT_TIME); // wait 40 us for most commands
        LCD_E1 = 0;
        
        wait_us(WAIT_TIME); // wait 40 us for most commands
        
        LCD_DATA   = lo;
        LCD_E1 = 1;
        wait_us(WAIT_TIME); // wait 40 us for most commands
        LCD_E1 = 0;
    }
        
    if(e2)
    {
        LCD_DATA  = hi;
        LCD_E2= 1;
        wait_us(WAIT_TIME); // wait 40 us for most commands
        LCD_E2= 0;
        
        wait_us(WAIT_TIME); // wait 40 us for most commands
        
        LCD_DATA   = lo;
        LCD_E2= 1;
        wait_us(WAIT_TIME); // wait 40 us for most commands
        LCD_E2= 0;
    }
}

/*****************************************************************************/
void LCD::writeCommand(char value, int e1, int e2){
    
    waitBusy();
    LCD_RS = 0;
    writeData(value,e1,e2);
}

/*****************************************************************************/
void LCD::writeChar(char value, int e1, int e2){
    //waitBusy();
    LCD_RS = 1;
    writeData(value,e1,e2);
}


/*****************************************************************************/
void LCD::putc(const char c)
{
    character(_row, _column, c);
}

/*****************************************************************************/
void LCD::printf(const char *message, ...)
{
    char buffer[128];
    va_list argptr;
    va_start(argptr, message);
    vsprintf( buffer, message, argptr);
    write (buffer);
    va_end(argptr);
}

/*****************************************************************************/
void LCD::write(const char* text) {
    //_row = 0;
    //_column = 0;
    int characterAmount =0;
    
    for(int i = 0; text[i] != '\0'; i++) {
        if (!isprint(text[i])) { 
            fprintf(stdout,"^%02x : %s ", text[i],text);
        }
        characterAmount++;
    }
    
    if (characterAmount > 40 - _column ) { 
        fprintf(stdout,"OVERFLOW+(%d+%d) %d: [%s] \n\r",_row, _column, characterAmount, text);
        characterAmount = 40 - _column ;
    }
        
    for (int i = 0; i < characterAmount && i < rows() * columns(); i++){
        if (isprint(text[i]))
            character(_row, _column, text[i]);
            
        wait_us(1);
    }
}

/*****************************************************************************/
void LCD::writeLine(int line, const char* text ) {
    
    _row = line;
    _column = 1;
    
    int characterAmount =strlen(text);
    
    int i=0;
    locate(_row,_column);
    
    while(i < columns()-1)
    {
        if ( i < characterAmount )
            putc( text[i]);
        else
            putc ( ' ');
            
        i++;
    }
}

/*****************************************************************************/
void LCD::writeCharacter(const char c, int row, int column) {
    locate(row, column);
    character(_row, _column, c);
}

/*****************************************************************************/
void LCD::writeCharacters(const char* text, int row, int column) {
    locate(row, column);
    
    int characterAmount =0;
    
    for(int i = 0; text[i] != '\0'; i++)
        characterAmount++;
        
    for (int i = 0; i < characterAmount  && i < columns() - column; i++){
        character(_row, _column, text[i]);
    }
}

/*****************************************************************************/
int LCD::address(int row, int column){
    
    int a=0x80;
    
    if(row < rows() && column < columns())
    {
        switch (row){
            case 0:
            case 1:
                a = 0x80 + (row * 0x40) + column;
                break;
            case 2:
            case 3:
                a = 0x80 + ((row-2) * 0x40) + column;
                break;
            default:
                break;
        }
    }
    
    return a;
}

/*****************************************************************************/
void LCD::character(int row, int column,  char c) {
    uint8_t a = address(row, column);
                
    if(row<2){
        writeCommand(a,1,0);
        writeChar(c,1,0);
    }
    else
    {
        writeCommand(a,0,1);
        writeChar(c,0,1);
    }
    
    //Update position
    if(_column < columns())
        _column++;
    if (_column >= columns()){
        #if 1
        if (_row == 0){
            _column = 0;
            _row++;
        }
        else{
            _row = 0;
            _column = 0;
        }
        #endif
    }
}

/*****************************************************************************/
void LCD::setCursorMode( int mode )
{
    if (mode) 
    {
        if(_row < 2)
            writeCommand(LCD_setDisplayBlink,1,0); 
        else
            writeCommand(LCD_setDisplayBlink,0,1); 
        
    } 
    else
    {
        writeCommand(LCD_setDisplayOn,1,1);  
    }
}