Contains necessary classes and functions for ELEC351
Diff: displayMaster/displayMaster.cpp
- Revision:
- 5:becb1545229d
- Parent:
- 4:d463eafbabed
diff -r d463eafbabed -r becb1545229d displayMaster/displayMaster.cpp --- a/displayMaster/displayMaster.cpp Thu Dec 28 12:34:20 2017 +0000 +++ b/displayMaster/displayMaster.cpp Tue Jan 09 11:25:52 2018 +0000 @@ -1,73 +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. This class contains blocking function */ +[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) { - _enable = DISABLE; // DISABLE at start - _commsBus[3].output(); // Reconfigure pin as output (MSB) - Thread::wait(20); // Powerup time - _commsBus = 0x03; // Pannel config instruction 1 - _enable = ENABLE; // Validate instruction - _enable = DISABLE; - Thread::wait(15); // Wait since BUSY flag not available yet - _commsBus = 0x03; // Pannel config instruction 2 - _enable = ENABLE; // Validate instruction - _enable = DISABLE; - Thread::wait(5); // Wait since BUSY flag not available yet - _commsBus = 0x03; // Pannel config instruction 3 - _enable = ENABLE; // Validate instruction - _enable = DISABLE; - Thread::wait(2); // Wait since BUSY flag not available yet - _commsBus = 0x02; // Pannel config instruction (4 bit mode) - _enable = ENABLE; // Validate instruction - _enable = DISABLE; - Thread::wait(2); // Wait since BUSY flag not available yet - writeChar(0x28, INSTRUCTION); // Function Set: 4-bit, 2 Line, 5x7 Dots - //writeChar(0x01, INSTRUCTION); // Clear Display (also clear DDRAM content) - writeChar(0x0C, INSTRUCTION); // Display = on, Cursor = off - writeChar(0x06, INSTRUCTION); // Entry Mode (Auto increment) - - writeChar(0x23, DATA); + _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 + _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 != _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) + _enable = DISABLE; // Leave DISABLED upon exit + _modeSel = WRITE; // Return to WRITE mode + _commsBus[3].output(); // Reconfigure pin as output (MSB) } -void C_displayMaster::writeChar(char instructions, bool REGISTER) + +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() { - _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 = (instructions>>4);// Top nibble - _enable = ENABLE; // validate signal - Thread::wait(20); - // busyCheck(); - _commsBus = (instructions); // Bottom nibble - _enable = ENABLE; // validate signal - // busyCheck(); - Thread::wait(20); + 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