Prepare for 4 bit mode of operation

Signed-off-by: Collin J. Doering <collin.doering@rekahsoft.ca>
This commit is contained in:
Collin J. Doering 2015-10-01 03:04:33 -04:00
parent 3ba737fc7b
commit 5777e2b831
2 changed files with 260 additions and 61 deletions

154
lcdLib.c
View File

@ -21,8 +21,6 @@
* Date: Sep 29, 2015 * Date: Sep 29, 2015
*/ */
//#include <avr/interrupt.h>
//#include <avr/power.h>
#include <util/delay.h> #include <util/delay.h>
// Include header // Include header
@ -42,48 +40,108 @@ void flashLED(uint8_t times) {
//------------------------------------ //------------------------------------
void clkLCD(void) { void clkLCD(void) {
LCD_CTRL_PORT |= 1 << LCD_ENABLE; LCD_ENABLE_PORT |= (1 << LCD_ENABLE);
_delay_us(LCD_DELAY); _delay_us(LCD_ENABLE_HIGH_DELAY);
LCD_CTRL_PORT &= ~(1 << LCD_ENABLE); LCD_ENABLE_PORT &= ~(1 << LCD_ENABLE);
_delay_us(LCD_DELAY); _delay_us(LCD_ENABLE_LOW_DELAY);
} }
void loop_until_LCD_BF_clear(void) { void loop_until_LCD_BF_clear(void) {
LCD_CTRL_PORT = (LCD_CTRL_PORT & ~(1 << LCD_RS)) | (1 << LCD_RW); // RS=0, RW=1 LCD_RS_PORT &= ~(1 << LCD_RS); // RS=0
LCD_DBUS_DDR &= ~(1 << LCD_BF); // Set LCD_BF as input 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 STATUS_LED_PORT |= 1 << STATUS_LED; // DEBUG
do { do {
clkLCD(); 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 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 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) { 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; LCD_DBUS_PORT = instr;
clkLCD(); clkLCD();
#endif
} }
void writeLCDInstr(uint8_t instr) { void writeLCDInstr(uint8_t instr) {
loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions
writeLCDInstr_(instr); writeLCDInstr_(instr);
} }
void writeCharToLCD_(char c) { void writeCharToLCD_(char c) {
LCD_CTRL_PORT |= (1 << LCD_RS); // RS=1 LCD_RS_PORT |= (1 << LCD_RS); // RS=1
LCD_CTRL_PORT &= ~(1 << LCD_RW); // RW=0 LCD_RW_PORT &= ~(1 << LCD_RW); // RW=0
#ifdef FOUR_BIT_MODE
writeLCDNibble_(c);
writeLCDNibble_(c << 4);
#else
LCD_DBUS_PORT = c; LCD_DBUS_PORT = c;
clkLCD(); clkLCD();
#endif
} }
void writeCharToLCD(char c) { void writeCharToLCD(char c) {
loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions
writeCharToLCD_(c); writeCharToLCD_(c);
} }
@ -96,49 +154,77 @@ void writeStringToLCD(const char* str) {
void clearDisplay(void) { void clearDisplay(void) {
writeLCDInstr(CMD_CLEAR_DISPLAY); writeLCDInstr(CMD_CLEAR_DISPLAY);
_delay_us(LCD_CLEAR_DISPLAY_DELAY);
} }
void returnHome(void) { void returnHome(void) {
writeLCDInstr(CMD_RETURN_HOME); writeLCDInstr(CMD_RETURN_HOME);
_delay_us(LCD_RETURN_HOME_DELAY);
} }
char readCharFromLCD(void) { /* char readCharFromLCD(void) { */
loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions /* 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_CTRL_PORT |= (1 << LCD_RW) | (1 << LCD_RW); // RS=RW=1 */
LCD_DBUS_DDR = 0; // Set all LCD_DBUS_PORT pins as inputs /* LCD_DBUS_DDR = 0; // Set all LCD_DBUS_PORT pins as inputs */
clkLCD(); /* clkLCD(); */
char c = LCD_DBUS_PIN; /* char c = LCD_DBUS_PIN; */
LCD_DBUS_DDR = 0xff; // Reset all LCD_DBUS_PORT pins to outputs /* LCD_DBUS_DDR = 0xff; // Reset all LCD_DBUS_PORT pins to outputs */
return c; /* return c; */
} /* } */
/* /*
Set all pins of LCD_DBUS_PORT, as well as pins LCD_RS, and LCD_RW, on Set all pins of LCD_DBUS, as well as pins LCD_RS, and LCD_RW as outputs
LCD_CTRL_PORT as outputs
*/ */
static inline void enableLCDOutput(void) { 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; 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 Set all pins of LCD_DBUS as well as LCD_RS, and LCD_RW as inputs (disabling their output)
inputs (disabling their output)
*/ */
static inline void disableLCDOutput(void) { 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; LCD_DBUS_DDR = 0;
#endif
} }
static inline void softwareLCDInitPulse(void) { static inline void softwareLCDInitPulse(void) {
enableLCDOutput(); 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; LCD_DBUS_PORT = CMD_INIT;
clkLCD(); clkLCD();
#endif
} }
/* /*
@ -148,7 +234,7 @@ void initLCD (void) {
enableLCDOutput(); enableLCDOutput();
// Wait minimum 15ms as per datasheet // Wait minimum 15ms as per datasheet
_delay_ms(LCD_INIT_DELAY0); _delay_us(LCD_INIT_DELAY0);
softwareLCDInitPulse(); softwareLCDInitPulse();

165
lcdLib.h
View File

@ -21,37 +21,143 @@
* Date: Sep 29, 2015 * 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 // Includes
#include <avr/io.h> #include <avr/io.h>
// 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_PORT PORTB
#define LCD_DBUS_DDR DDRB #define LCD_DBUS_DDR DDRB
#define LCD_DBUS_PIN PINB #define LCD_DBUS_PIN PINB
#define LCD_CTRL_PORT PORTD // This must be set in default mode to the MSB of the data lines
#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
#define LCD_BF PB7 #define LCD_BF PB7
// LCD in 4 bit mode (default is 8 bit mode)
//#define FOUR_BIT_MODE
// LCD delays (in microseconds when unspecified) // EIGHT_BIT_ARBITRARY_PIN_MODE specific settings
#define LCD_DELAY 25 #ifdef EIGHT_BIT_ARBITRARY_PIN_MODE
#define LCD_INIT_DELAY0 15 // milliseconds #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_DELAY1 8200
#define LCD_INIT_DELAY2 200 #define LCD_INIT_DELAY2 200
@ -59,6 +165,7 @@
#define LCD_RETURN_HOME_DELAY 16000 #define LCD_RETURN_HOME_DELAY 16000
#define LCD_GENERIC_INSTR_DELAY 50 #define LCD_GENERIC_INSTR_DELAY 50
/* LCD Commands */ /* LCD Commands */
// Simple commands with no options // Simple commands with no options
@ -110,15 +217,21 @@ void clkLCD(void);
void loop_until_LCD_BF_clear(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); void clearDisplay(void);