Read support implemented

Implemented functions for reading the LCD's DDRAM/CGRAM. Which is read
is dependent on the last 'address set' instruction. The functions
implemented are as follows:

Internal use only:
- readLCDDBusByte_
  No busy flag (BF) check. Sets RS=RW=1 and the data bus lines as
  inputs, reads them regardless of mode and returns the byte read.

Externally accessable:
- readCharFromLCD
- readLCDLine
- readCharsFromLCD

Note: more thorough documentation of the aforementioned functions is
required, though all have been tested and seen to be working.

Additionally, renamed the following for clarity's sake:
 enableLCDOutput  -> setLCDDBusAsOutputs
 disableLCDOutput -> setLCDDBusAsInputs

Signed-off-by: Collin J. Doering <collin.doering@rekahsoft.ca>
This commit is contained in:
Collin J. Doering 2015-10-28 04:30:40 -04:00
parent 3fcbf653a9
commit 85fb4eca6a
2 changed files with 123 additions and 28 deletions

131
lcdLib.c
View File

@ -206,6 +206,49 @@ static void writeCharToLCD_(char c) {
writeLCDDBusByte_(c);
}
static uint8_t readLCDDBusByte_(void) {
LCD_RS_PORT |= (1 << LCD_RS); // RS=1
LCD_RW_PORT |= (1 << LCD_RW); // RW=1
LCD_ENABLE_PORT |= (1 << LCD_ENABLE);
_delay_us(1); // 'delay data time' and 'enable pulse width'
// Read data
char c = 0;
#if defined(FOUR_BIT_MODE)
if (LCD_DBUS7_PIN & (1 << LCD_DBUS7)) c |= (1 << 7);
if (LCD_DBUS6_PIN & (1 << LCD_DBUS6)) c |= (1 << 6);
if (LCD_DBUS5_PIN & (1 << LCD_DBUS5)) c |= (1 << 5);
if (LCD_DBUS4_PIN & (1 << LCD_DBUS4)) c |= (1 << 4);
LCD_ENABLE_PORT &= ~(1 << LCD_ENABLE);
_delay_us(1); // 'address hold time', 'data hold time' and 'enable cycle width'
LCD_ENABLE_PORT |= (1 << LCD_ENABLE);
_delay_us(1); // 'delay data time' and 'enable pulse width'
if (LCD_DBUS7_PIN & (1 << LCD_DBUS7)) c |= (1 << 3);
if (LCD_DBUS6_PIN & (1 << LCD_DBUS6)) c |= (1 << 2);
if (LCD_DBUS5_PIN & (1 << LCD_DBUS5)) c |= (1 << 1);
if (LCD_DBUS4_PIN & (1 << LCD_DBUS4)) c |= (1 << 0);
#elif defined(EIGHT_BIT_ARBITRARY_PIN_MODE)
if (LCD_DBUS7_PIN & (1 << LCD_DBUS7)) c |= (1 << 7);
if (LCD_DBUS6_PIN & (1 << LCD_DBUS6)) c |= (1 << 6);
if (LCD_DBUS5_PIN & (1 << LCD_DBUS5)) c |= (1 << 5);
if (LCD_DBUS4_PIN & (1 << LCD_DBUS4)) c |= (1 << 4);
if (LCD_DBUS3_PIN & (1 << LCD_DBUS3)) c |= (1 << 3);
if (LCD_DBUS2_PIN & (1 << LCD_DBUS2)) c |= (1 << 2);
if (LCD_DBUS1_PIN & (1 << LCD_DBUS1)) c |= (1 << 1);
if (LCD_DBUS0_PIN & (1 << LCD_DBUS0)) c |= (1 << 0);
#else
c = LCD_DBUS_PIN;
#endif
LCD_ENABLE_PORT &= ~(1 << LCD_ENABLE);
_delay_us(1); // 'address hold time', 'data hold time' and 'enable cycle width'
return c;
}
/*
Given a character string, and a uint8_t pointer, reads the character string until a
non-numerical ASCII character, returning the integer representation of the number read. At
@ -237,13 +280,9 @@ static uint8_t readASCIINumber(char* str, uint8_t* found_num, char** new_loc) {
}
/*
Set all pins of LCD_DBUS, as well as pins LCD_RS, and LCD_RW as outputs
Set all pins of LCD_DBUS as outputs
*/
static inline void enableLCDOutput(void) {
LCD_RS_DDR |= (1 << LCD_RS);
LCD_RW_DDR |= (1 << LCD_RW);
LCD_ENABLE_DDR |= (1 << LCD_ENABLE);
static inline void setLCDDBusAsOutputs(void) {
#if defined (FOUR_BIT_MODE) || defined (EIGHT_BIT_ARBITRARY_PIN_MODE)
LCD_DBUS7_DDR |= (1 << LCD_DBUS7);
LCD_DBUS6_DDR |= (1 << LCD_DBUS6);
@ -261,13 +300,9 @@ static inline void enableLCDOutput(void) {
}
/*
Set all pins of LCD_DBUS as well as LCD_RS, and LCD_RW as inputs (disabling their output)
Set all pins of LCD_DBUS as inputs (disabling their output)
*/
static inline void disableLCDOutput(void) {
LCD_RS_DDR &= ~(1 << LCD_RS);
LCD_RW_DDR &= ~(1 << LCD_RW);
LCD_ENABLE_DDR &= ~(1 << LCD_ENABLE);
static inline void setLCDDBusAsInputs(void) {
#if defined (FOUR_BIT_MODE) || defined (EIGHT_BIT_ARBITRARY_PIN_MODE)
LCD_DBUS7_DDR &= ~(1 << LCD_DBUS7);
LCD_DBUS6_DDR &= ~(1 << LCD_DBUS6);
@ -289,7 +324,6 @@ static inline void disableLCDOutput(void) {
pause must follow before sending new commands to the LCD using writeLCD*_ functions.
*/
static inline void softwareLCDInitPulse(void) {
enableLCDOutput();
LCD_RS_PORT &= ~(1 << LCD_RS); // RS=0
LCD_RW_PORT &= ~(1 << LCD_RW); // RW=0
@ -308,7 +342,12 @@ static inline void softwareLCDInitPulse(void) {
Do software initialization as specified by the datasheet
*/
void initLCD(void) {
enableLCDOutput();
// Set LCD_RS, LCD_RW and LCD_ENABLE as outputs
LCD_RS_DDR |= (1 << LCD_RS);
LCD_RW_DDR |= (1 << LCD_RW);
LCD_ENABLE_DDR |= (1 << LCD_ENABLE);
setLCDDBusAsOutputs();
_delay_us(LCD_INIT_DELAY0); // Wait minimum 15ms as per datasheet
softwareLCDInitPulse();
@ -796,22 +835,66 @@ void displayOn(void) {
//-----------------------------------------------------------------------------------------------
/* char readCharFromLCD(void) { */
/* loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions */
char readCharFromLCD(uint8_t row, uint8_t column) {
uint8_t old_row, old_column;
getCursorPosition(&old_row, &old_column);
/* LCD_CTRL_PORT |= (1 << LCD_RW) | (1 << LCD_RW); // RS=RW=1 */
/* LCD_DBUS_DDR = 0; // Set all LCD_DBUS_PORT pins as inputs */
/* clkLCD(); */
setCursorPosition(row, column);
/* char c = LCD_DBUS_PIN; */
/* LCD_DBUS_DDR = 0xff; // Reset all LCD_DBUS_PORT pins to outputs */
/* return c; */
/* } */
loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions
setLCDDBusAsInputs();
char c = readLCDDBusByte_();
setLCDDBusAsOutputs();
setCursorPosition(old_row, old_column);
return c;
}
void readLCDLine(uint8_t i, char* str) {
readCharsFromLCD(i, 1, i, LCD_CHARACTERS_PER_LINE, str, LCD_CHARACTERS_PER_LINE + 1);
}
//---------------------------------------------------------------------------------------------
// Advanced functions for special cases
void readCharsFromLCD(uint8_t from_row, uint8_t from_column, uint8_t to_row, uint8_t to_column, char* str, uint8_t len) {
uint8_t old_row, old_column;
getCursorPosition(&old_row, &old_column);
setCursorPosition(from_row, from_column);
for (uint8_t i = 0; i < len - 1 && from_row <= to_row; i++) {
if (from_row == LCD_NUMBER_OF_LINES && from_column == LCD_CHARACTERS_PER_LINE) {
// Last character on screen
loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions
setLCDDBusAsInputs();
*(str++) = readLCDDBusByte_();
setLCDDBusAsOutputs();
} else if (from_column == LCD_CHARACTERS_PER_LINE) { // End of line (but not last one)
loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions
setLCDDBusAsInputs();
*(str++) = readLCDDBusByte_();
setLCDDBusAsOutputs();
from_row += 1;
from_column = 1;
setCursorPosition(from_row, from_column);
} else {
loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions
setLCDDBusAsInputs();
*(str++) = readLCDDBusByte_();
setLCDDBusAsOutputs();
from_column++;
}
}
// Ensure array is terminated with null character
*str = '\0';
setCursorPosition(old_row, old_column);
setLCDDBusAsOutputs();
}
/*
Initialize LCD using the internal reset circuitry.
@ -820,7 +903,7 @@ void displayOn(void) {
modes as well the 4-bit mode.
*/
void initLCDByInternalReset(void) {
enableLCDOutput();
setLCDDBusAsOutputs();
// Function set (8-bit interface; 2 lines with 5x7 dot character font)
writeLCDInstr_(INSTR_FUNC_SET | (1 << INSTR_FUNC_SET_DL) | (1 << INSTR_FUNC_SET_N));

View File

@ -178,18 +178,30 @@ void displayOff(void);
*/
void displayOn(void);
//---------------------------------------------------------------------------------------------
/*
UNIMPLEMENTED
/**
Read a single character from the row and column given (1 based) returning the cursor to
its previous original position.
*/
char readCharFromLCD(void);
char readCharFromLCD(uint8_t row, uint8_t column);
/**
Read a line i (ones based) into str.
*/
void readLCDLine(uint8_t i, char* str);
//---------------------------------------------------------------------------------------------
// Advanced functions for special cases
/**
Read len characters from (from_row, from_column) to (to_row, to_column) returning the cursor
to its original position after the read. Upon success (not overflowing the screen), 0 is
returned; otherwise non zero will be returned. The str pointer will be updated with the
characters read from the screen. Even in the case of failure, str may be partially populated.
*/
void readCharsFromLCD(uint8_t from_row, uint8_t from_column, uint8_t to_row, uint8_t to_column, char* str, uint8_t len);
/**
Initialize the LCD display via its internal reset circuit.