ELEC351 SUBMISSION - Same as on the DLE

/media/uploads/Luka_Danilovic/elec_315_prototype_assembly.jpg

ELEC351_LIBRARY/displayMaster/displayMaster.cpp

Committer:
Luka_Danilovic
Date:
2018-01-10
Revision:
0:c66224a27cf8

File content as of revision 0:c66224a27cf8:

#include "mbed.h"
#include "displayMaster.hpp"

////////////////////////////////////////////////////////////////////////////////
//                      INCOMPLETE - RUN OUT OF TIME TO DEBUG                 //
////////////////////////////////////////////////////////////////////////////////

/* Instructions on using the 16x2 LCD panel are found here:
[https://www.8051projects.net/lcd-interfacing/lcd-4-bit.php]                  */
/* N.B. I did the code from scratch since I do not have the code from ELEC230 */
/* N.B. This class contains blocking function so it goes into its own thread  */

C_displayMaster::C_displayMaster(PinName D1, PinName D2, PinName D3 , PinName D4 , PinName RS , PinName RW, PinName EN)
    :   // Initialisation of the instance
    _commsBus(D1, D2, D3, D4),
    _registerSel(RS),
    _modeSel(RW),
    _enable(EN)
{
    _registerSel    = INSTRUCTION;  // command mode
    _modeSel        = WRITE;        // write mode

    Thread::wait(20);               // Wait 20ms to ensure powered up

    for (int i=0; i<3; i++) {       // Three times
        _enable     = DISABLE;      // Invalidate signal
        _commsBus   = 0x03;         // Send command for powerup
        _enable     = ENABLE;       // Validate signal
        Thread::wait(20);           // Wait since BUSY flag is not yet available
    }

    _enable     = DISABLE;          // Invalidate signal
    _commsBus   = 0x03;             // Send command for 4 bit mode
    _enable     = ENABLE;           // Validate signal
    Thread::wait(20);               // Wait since BUSY flag is not yet available

    // BUSY flag is now available, Can use "writeChar"                        //

    writeChar(0x28, INSTRUCTION);   // 4-bit, 2 Line, 5x7 Dots
    writeChar(0x0C, INSTRUCTION);   // Display on Cursor off
    writeChar(0x04, INSTRUCTION);   // Entry mode - no increment & no display shift
    clear();                        // Clear display for writing (DDRAM cleared)

//    writeChar(0b00100011, DATA);    // Write Test "#" symbol
//    Thread::wait(1000);             // Wait 1 second
//    clear();                        // Clear Test "#" symbol
}


//****************************************************************************//
void C_displayMaster::writeChar(int Char, bool REGISTER)
{
    _enable      = DISABLE;         // DISABLE at start
    _commsBus[3].output();          // Reconfigure pin as output (MSB)
    _registerSel = REGISTER;        // Chose register to comunicate with
    _modeSel     = WRITE;           // WRITE to register

    _commsBus    = (Char>>4);       // Top nibble
    _enable      = ENABLE;          // Validate signal
    _enable = DISABLE;              // Invalidate signal
    busyCheck();                    // Chek if clear to write more

    _commsBus    = (Char>>0);       // Bottom nibble
    _enable      = ENABLE;          // Validate signal
    _enable = DISABLE;              // Invalidate signal
    busyCheck();                    // Chek if clear to write more
}


void C_displayMaster::busyCheck()
{
    _enable      = DISABLE;         // DISABLE at start
    _commsBus[3].input();           // Input to listen for BUSY flag (MSB)
    _registerSel = INSTRUCTION;     // Comunicate with INSTRUCTION register
    _modeSel     = READ;            // READ from register
    _enable      = ENABLE;          // Listen for BUSY flag
    while(_commsBus[3]) {
        _enable != _enable;         // Repeat read while BUSY flag is set
    }
    _enable      = DISABLE;         // Leave DISABLED upon exit
    _modeSel     = WRITE;           // Return to WRITE mode
    _commsBus[3].output();          // Reconfigure pin as output (MSB)
}


void C_displayMaster::calcDDRAM(int col, int row)
{
    /* The following two IF statments create a continous display meaning that
    running of the right edge return you to the left edge and running of the
    bottom edge return you to the top row.                                    */

    if (col>16) {                   // If coloumn is outside of Right edge
        col =  1;                   // Go back to start of row
    } else if (col<1) {             // OR If coloumn is outside of Left edge
        col =  1;                   // Go back to start of row
    } else {                        // Othetwise
        col = col;                  // No change in col
    }

    if (row>2) {                    // If row is outside of Bottom edge
        row =  1;                   // Go back to top row
    } else if (row<1) {             // OR If row is outside of Top edge
        row =  1;                   // Go back to top row
    } else {                        // Othetwise
        row = row;                  // No change in row
    }

    _ADR = (1<<7)+((1<<6)*row-1)+col-1;   // Recalculate DDRAM address
}


void C_displayMaster::clear()
{
    writeChar(0x01, INSTRUCTION);   // Clear display for writing (DDRAM cleared)
    _col = 1;                       // First coloumn
    _row = 1;                       // First row
    calcDDRAM(_col, _row);          // Get DDRAM address for writing next char
}


int C_displayMaster::_getc()
{
    return -1;                      // Return Fail value since function has no purpose but is needed for character Stream
}


int C_displayMaster::_putc(int character)
{
    if (character=='\n') {          // IF new line
        _row++;                     // Go to new row
        _col = 1;                   // Go to start of row
    } else if (character=='\r') {   // IF carridge return
        _col = 1;                   // Go to start of line
    } else {                        // ELSE
        
        calcDDRAM(_col, _row);          // Get cursor new address (N.B this function also creates a continous display. More details in function).
        writeChar(_ADR, INSTRUCTION);   // Set cursor to position
        writeChar(character, DATA);     // Write character
        
        _col++;                     // Increment cursor position
        if (_col>16) {              // IF end of row go to new row
            _row++;                 // Go to new row
            _col = 1;               // Go to start of row
        }
    }
    return character;               // Return what was written to indicate sucess
}