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

156
lcdLib.c
View File

@ -21,8 +21,6 @@
* Date: Sep 29, 2015
*/
//#include <avr/interrupt.h>
//#include <avr/power.h>
#include <util/delay.h>
// 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();

165
lcdLib.h
View File

@ -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 <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_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);