diff --git a/lcdLib.c b/lcdLib.c index 36f9b08..a2ef2a8 100644 --- a/lcdLib.c +++ b/lcdLib.c @@ -21,8 +21,6 @@ * Date: Sep 29, 2015 */ -//#include -//#include #include // Include header @@ -42,48 +40,108 @@ void flashLED(uint8_t times) { //------------------------------------ void clkLCD(void) { - LCD_CTRL_PORT |= 1 << LCD_ENABLE; - _delay_us(LCD_DELAY); - LCD_CTRL_PORT &= ~(1 << LCD_ENABLE); - _delay_us(LCD_DELAY); + LCD_ENABLE_PORT |= (1 << LCD_ENABLE); + _delay_us(LCD_ENABLE_HIGH_DELAY); + LCD_ENABLE_PORT &= ~(1 << LCD_ENABLE); + _delay_us(LCD_ENABLE_LOW_DELAY); } void loop_until_LCD_BF_clear(void) { - LCD_CTRL_PORT = (LCD_CTRL_PORT & ~(1 << LCD_RS)) | (1 << LCD_RW); // RS=0, RW=1 - LCD_DBUS_DDR &= ~(1 << LCD_BF); // Set LCD_BF as input + LCD_RS_PORT &= ~(1 << LCD_RS); // RS=0 + LCD_RW_PORT |= (1 << LCD_RW); // RW=1 + + // Set LCD_BF as input +#ifdef FOUR_BIT_MODE + LCD_DBUS7_PORT &= ~(1 << LCD_BF); +#else + LCD_DBUS_DDR &= ~(1 << LCD_BF); +#endif STATUS_LED_PORT |= 1 << STATUS_LED; // DEBUG do { clkLCD(); - } while (bit_is_clear(LCD_DBUS_PIN, LCD_BF)); - /* loop_until_bit_is_clear(LCD_DBUS_PIN, LCD_BF); */ + } +#ifdef FOUR_BIT_MODE + while (bit_is_clear(LCD_DBUS7_PIN, LCD_BF)); + #else + while (bit_is_clear(LCD_DBUS_PIN, LCD_BF)); +#endif STATUS_LED_PORT &= ~(1 << STATUS_LED); // DEBUG - + +#ifdef FOUR_BIT_MODE + LCD_DBUS7_DDR = 0; + LCD_DBUS6_DDR = 0; + LCD_DBUS5_DDR = 0; + LCD_DBUS4_DDR = 0; +#else LCD_DBUS_DDR = 0xff; // Reset all LCD_DBUS_PORT pins as outputs +#endif +} + +#ifdef FOUR_BIT_MODE +/* + Writes one nibble to the LCD data bus. Does not touch the RS or RW control lines. + Note: the bits that are sent are the four MSBs of the given argument + */ +void writeLCDNibble_(uint8_t b) { + // Reset data lines to zeros + LCD_DBUS7_PORT &= ~(1 << LCD_DBUS7); + LCD_DBUS6_PORT &= ~(1 << LCD_DBUS6); + LCD_DBUS5_PORT &= ~(1 << LCD_DBUS5); + LCD_DBUS4_PORT &= ~(1 << LCD_DBUS4); + + // Write 1's where appropriate on data lines + if (b & (1 << 7)) LCD_DBUS7_PORT |= (1 << LCD_DBUS7); + if (b & (1 << 6)) LCD_DBUS6_PORT |= (1 << LCD_DBUS6); + if (b & (1 << 5)) LCD_DBUS5_PORT |= (1 << LCD_DBUS5); + if (b & (1 << 4)) LCD_DBUS4_PORT |= (1 << LCD_DBUS4); + + // Pulse the enable line + clkLCD(); +} +#endif + +/* + Write a byte to the LCD data bus. Does not touch the RS or RW control lines. +*/ +void writeLCDByte_(uint8_t b) { + LCD_DBUS_PORT = b; + clkLCD(); } void writeLCDInstr_(uint8_t instr) { - LCD_CTRL_PORT &= ~((1 << LCD_RS) | (1 << LCD_RW)); // RS=RW=0 +LCD_RS_PORT &= ~(1 << LCD_RS); // RS=0 +LCD_RW_PORT &= ~(1 << LCD_RW); // RW=0 + +#ifdef FOUR_BIT_MODE + writeLCDNibble_(instr); + writeLCDNibble_(instr << 4); +#else LCD_DBUS_PORT = instr; clkLCD(); +#endif } void writeLCDInstr(uint8_t instr) { loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions - writeLCDInstr_(instr); } void writeCharToLCD_(char c) { - LCD_CTRL_PORT |= (1 << LCD_RS); // RS=1 - LCD_CTRL_PORT &= ~(1 << LCD_RW); // RW=0 + LCD_RS_PORT |= (1 << LCD_RS); // RS=1 + LCD_RW_PORT &= ~(1 << LCD_RW); // RW=0 + +#ifdef FOUR_BIT_MODE + writeLCDNibble_(c); + writeLCDNibble_(c << 4); +#else LCD_DBUS_PORT = c; clkLCD(); +#endif } void writeCharToLCD(char c) { loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions - writeCharToLCD_(c); } @@ -96,49 +154,77 @@ void writeStringToLCD(const char* str) { void clearDisplay(void) { writeLCDInstr(CMD_CLEAR_DISPLAY); - _delay_us(LCD_CLEAR_DISPLAY_DELAY); } void returnHome(void) { writeLCDInstr(CMD_RETURN_HOME); - _delay_us(LCD_RETURN_HOME_DELAY); } -char readCharFromLCD(void) { - loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions +/* char readCharFromLCD(void) { */ +/* loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions */ - 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(); +/* 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(); */ - char c = LCD_DBUS_PIN; - LCD_DBUS_DDR = 0xff; // Reset all LCD_DBUS_PORT pins to outputs - return c; -} +/* char c = LCD_DBUS_PIN; */ +/* LCD_DBUS_DDR = 0xff; // Reset all LCD_DBUS_PORT pins to outputs */ +/* return c; */ +/* } */ /* - Set all pins of LCD_DBUS_PORT, as well as pins LCD_RS, and LCD_RW, on - LCD_CTRL_PORT as outputs + Set all pins of LCD_DBUS, as well as pins LCD_RS, and LCD_RW as outputs */ static inline void enableLCDOutput(void) { - LCD_CTRL_DDR |= (1 << LCD_RS) | (1 << LCD_RW) | (1 << LCD_ENABLE); + LCD_RS_DDR |= (1 << LCD_RS); + LCD_RW_DDR |= (1 << LCD_RW); + LCD_ENABLE_DDR |= (1 << LCD_ENABLE); + +#if defined (FOUR_BIT_MODE) || defined (EIGHT_BIT_ARBITRARY_PIN_MODE) + LCD_DBUS7_DDR |= (1 << LCD_DBUS7); + LCD_DBUS6_DDR |= (1 << LCD_DBUS6); + LCD_DBUS5_DDR |= (1 << LCD_DBUS5); + LCD_DBUS4_DDR |= (1 << LCD_DBUS4); +#ifdef EIGHT_BIT_ARBITRARY_PIN_MODE + LCD_DBUS3_DDR |= (1 << LCD_DBUS3); + LCD_DBUS2_DDR |= (1 << LCD_DBUS2); + LCD_DBUS1_DDR |= (1 << LCD_DBUS1); + LCD_DBUS0_DDR |= (1 << LCD_DBUS0); +#endif +#else LCD_DBUS_DDR = 0xff; +#endif } /* - Set all pins of LCD_DBUS_PORT as well as LCD_RS, and LCD_RW on LCD_CTRL_PORT as - inputs (disabling their output) + Set all pins of LCD_DBUS as well as LCD_RS, and LCD_RW as inputs (disabling their output) */ static inline void disableLCDOutput(void) { - LCD_CTRL_DDR &= ~((1 << LCD_RS) | (1 << LCD_RW) | (1 << LCD_ENABLE)); + LCD_RS_DDR &= ~(1 << LCD_RS); + LCD_RW_DDR &= ~(1 << LCD_RW); + LCD_ENABLE_DDR &= ~(1 << LCD_ENABLE); + +#ifdef FOUR_BIT_MODE +LCD_DBUS7 &= ~(1 << LCD_DBUS7); +LCD_DBUS6 &= ~(1 << LCD_DBUS6); +LCD_DBUS5 &= ~(1 << LCD_DBUS5); +LCD_DBUS4 &= ~(1 << LCD_DBUS4); +#else LCD_DBUS_DDR = 0; +#endif } static inline void softwareLCDInitPulse(void) { enableLCDOutput(); - LCD_CTRL_PORT &= ~((1 << LCD_RS) | (1 << LCD_RW)); // RS=RW=0 + LCD_RS_PORT &= ~(1 << LCD_RS); // RS=0 + LCD_RW_PORT &= ~(1 << LCD_RW); // RW=0 + +#ifdef FOUR_BIT_MODE + writeLCDNibble_(CMD_INIT); +#else LCD_DBUS_PORT = CMD_INIT; clkLCD(); +#endif } /* @@ -148,7 +234,7 @@ void initLCD (void) { enableLCDOutput(); // Wait minimum 15ms as per datasheet - _delay_ms(LCD_INIT_DELAY0); + _delay_us(LCD_INIT_DELAY0); softwareLCDInitPulse(); diff --git a/lcdLib.h b/lcdLib.h index 4184fcb..b3fcc9c 100644 --- a/lcdLib.h +++ b/lcdLib.h @@ -21,37 +21,143 @@ * Date: Sep 29, 2015 */ +/* + Usage + ===== + + Operates in 3 mutually exclusive modes: + 1. Default Mode + 8-bit mode that requires all its data bus lines be on the same PORT. + 2. EIGHT_BIT_ARBITRARY_PIN_MODE + 8-bit mode that allows the data bus lines to use any IO pin. + 3. FOUR_BIT_MODE + 4-bit mode that allows the data bus lines to use any IO pin. + */ + // Includes #include -// LCD data bus PORT, PIN and DDR + +/* Modes */ + +// Default mode: 8-bit data bus + +// 8-bit mode with data bus on arbitrary pins +//#define EIGHT_BIT_ARBITRARY_PIN_MODE + +// LCD in 4-bit mode (default is 8 bit mode) +//#define FOUR_BIT_MODE + +// Mode sanity check +#if defined (EIGHT_BIT_ARBITRARY_PIN_MODE) && defined (FOUR_BIT_MODE) +#error "EIGHT_BIT_ARBITRARY_PIN_MODE and FOUR_BIT_MODE are mutually exclusive. Choose one." +#endif + + +/* All mode options */ + +#define LCD_RS PD2 +#define LCD_RS_PORT PORTD +#define LCD_RS_DDR DDRD + +#define LCD_RW PD3 +#define LCD_RW_PORT PORTD +#define LCD_RW_DDR DDRD + +#define LCD_ENABLE PD4 +#define LCD_ENABLE_PORT PORTD +#define LCD_ENABLE_DDR DDRD + +/* Mode specific settings */ + +// Default Mode +// LCD data bus PORT, PIN and DDR. #define LCD_DBUS_PORT PORTB + #define LCD_DBUS_DDR DDRB #define LCD_DBUS_PIN PINB -#define LCD_CTRL_PORT PORTD -#define LCD_CTRL_DDR DDRD - -#define LCD_RS PD2 -#define LCD_RW PD3 -#define LCD_ENABLE PD4 - -#define LCD_DBUS0 PB0 -#define LCD_DBUS1 PB1 -#define LCD_DBUS2 PB2 -#define LCD_DBUS3 PB3 -#define LCD_DBUS4 PB4 -#define LCD_DBUS5 PB5 -#define LCD_DBUS6 PB6 -#define LCD_DBUS7 PB7 +// This must be set in default mode to the MSB of the data lines #define LCD_BF PB7 -// LCD in 4 bit mode (default is 8 bit mode) -//#define FOUR_BIT_MODE -// LCD delays (in microseconds when unspecified) -#define LCD_DELAY 25 -#define LCD_INIT_DELAY0 15 // milliseconds +// EIGHT_BIT_ARBITRARY_PIN_MODE specific settings +#ifdef EIGHT_BIT_ARBITRARY_PIN_MODE +#define LCD_DBUS0 PB0 +#define LCD_DBUS0_PORT PORTB +#define LCD_DBYS0_DDR DDRB +#define LCD_DBUS0_PIN PINB + +#define LCD_DBUS1 PB1 +#define LCD_DBUS1_PORT PORTB +#define LCD_DBUS1_DDR DDRB +#define LCD_DBUS1_PIN PINB + +#define LCD_DBUS2 PB2 +#define LCD_DBUS2_PORT PORTB +#define LCD_DBUS2_DDR DDRB +#define LCD_DBUS2_PIN PINB + +#define LCD_DBUS3 PB3 +#define LCD_DBUS3_PORT PORTB +#define LCD_DBUS3_DDR DDRB +#define LCD_DBUS3_PIN PINB + +#define LCD_DBUS4 PB4 +#define LCD_DBUS4_PORT PORTB +#define LCD_DBUS4_DDR DDRB +#define LCD_DBUS4_PIN PINB + +#define LCD_DBUS5 PB5 +#define LCD_DBUS5_PORT PORTB +#define LCD_DBUS5_DDR DDRB +#define LCD_DBUS5_PIN PINB + +#define LCD_DBUS6 PB6 +#define LCD_DBUS6_PORT PORTB +#define LCD_DBUS6_DDR DDRB +#define LCD_DBUS6_PIN PINB + +#define LCD_DBUS7 PB7 +#define LCD_DBUS7_PORT PORTB +#define LCD_DBUS7_DDR DDRB +#define LCD_DBUS7_PIN PINB +#endif + +// FOUR_BIT_MODE specific settings +#ifdef FOUR_BIT_MODE +#define LCD_DBUS4 PB4 +#define LCD_DBUS4_PORT PORTB +#define LCD_DBUS4_DDR DDRB +#define LCD_DBUS4_PIN PINB + +#define LCD_DBUS5 PB5 +#define LCD_DBUS5_PORT PORTB +#define LCD_DBUS5_DDR DDRB +#define LCD_DBUS5_PIN PINB + +#define LCD_DBUS6 PB6 +#define LCD_DBUS6_PORT PORTB +#define LCD_DBUS6_DDR DDRB +#define LCD_DBUS6_PIN PINB + +#define LCD_DBUS7 PB7 +#define LCD_DBUS7_PORT PORTB +#define LCD_DBUS7_DDR DDRB +#define LCD_DBUS7_PIN PINB +#endif + +#if defined (FOUR_BIT_MODE) || defined (EIGHT_BIT_ARBITRARY_PIN_MODE) +#undef LCD_BF +#define LCD_BF LCD_DBUS7 +#endif + + +/* LCD delays (in microseconds when unspecified) */ + +#define LCD_ENABLE_HIGH_DELAY 25 +#define LCD_ENABLE_LOW_DELAY 25 +#define LCD_INIT_DELAY0 15000 #define LCD_INIT_DELAY1 8200 #define LCD_INIT_DELAY2 200 @@ -59,6 +165,7 @@ #define LCD_RETURN_HOME_DELAY 16000 #define LCD_GENERIC_INSTR_DELAY 50 + /* LCD Commands */ // Simple commands with no options @@ -110,15 +217,21 @@ void clkLCD(void); void loop_until_LCD_BF_clear(void); -void writeLCDInstr_(uint8_t instr); +#ifdef FOUR_BIT_MODE +void writeLCDNibble_(uint8_t); +#endif -void writeLCDInstr(uint8_t instr); +void writeLCDByte_(uint8_t); -void writeCharToLCD_(char c); +void writeLCDInstr_(uint8_t); -void writeCharToLCD(char c); +void writeLCDInstr(uint8_t); -void writeStringToLCD(const char* str); +void writeCharToLCD_(char); + +void writeCharToLCD(char); + +void writeStringToLCD(const char*); void clearDisplay(void);