Luka Danilovic
/
ELEC351_10497267_SUBMISSION
ELEC351 SUBMISSION - Same as on the DLE
Diff: ELEC351_LIBRARY/displayMaster/displayMaster.cpp
- Revision:
- 0:c66224a27cf8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ELEC351_LIBRARY/displayMaster/displayMaster.cpp Wed Jan 10 09:49:43 2018 +0000 @@ -0,0 +1,147 @@ +#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 +} \ No newline at end of file