Need ideas and suggestions on my project

Hi.

So I am writing an LCD library for Arduino which is based on HD44780U driver. I am writing it purely in C, because it's fun and I wouldn't really be able to copy the original LCD library(given that my programming skill is below average). The library is not good as the original one and lacks a lot of things, which can be improved.

That's being said, for now I want some help to implement 4-bit mode on my library. I have a few ideas already(it might not be efficient) so I would like some suggestions from folks. I also has posted my code in github if anyone wanna contribute to it(see my signature).

In my LCDinC.h

//LCDinC.h

#ifdef __cplusplus
extern "C" {
#endif

#ifndef LCDinC_h
#define LCDinC_h

#include "Arduino.h"

/* user available commands */
void lcd_setPins(uint8_t rs, uint8_t en, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
void lcd_init(void);
void lcd_write(uint8_t *pChar);
void lcd_setCursor(uint8_t col, uint8_t row);
void lcd_clear(void);

/* low level commands */
void send_cmd(uint8_t pCmd);
void send_data(uint8_t pData);
void send_pulse(void);

#endif

#ifdef __cplusplus
} // extern "C"
#endif

In my LCDinC.c
//LCDinC.cpp

//LCDinC.cpp
#include "LCDinC.h"

enum{ 
	RS,
	EN
};

uint8_t pins_control[2];
uint8_t pins_data[8];

void lcd_setPins(uint8_t rs, uint8_t en, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
	//instrucion register pins
	pins_control[RS] = rs; 
	pins_control[EN] = en;
	
	//data register pins
	pins_data[0] = d0;
	pins_data[1] = d1;
	pins_data[2] = d2;
	pins_data[3] = d3;
	pins_data[4] = d4;
	pins_data[5] = d5;
	pins_data[6] = d6;
	pins_data[7] = d7;
}

void lcd_init(void) 
{
	delay(50);
	for (uint8_t i = 0; i < 2; i++)
	{
		pinMode(pins_control[i], 1);
		digitalWrite(pins_control[i], 0);
	}

	for (uint8_t i = 0; i < 8; i++)
	{
		pinMode(pins_data[i], 1);
		digitalWrite(pins_data[i], 0);
	}

	//initialization by instruction as in datasheet. also known as wake-up call
	send_cmd(0b00110000);
	delay(5);
	
	send_cmd(0b00110000);
	delay(1);
	
	send_cmd(0b00110000);
	delay(1);

	//init LCD 2 lines, 5x8
	send_cmd(0b00111000);
	delay(5);

	//display on, cursor off
	send_cmd(0b00001100); 

	//shift cursor right
	send_cmd(0b00000110);

	//line 1, position 1
	send_cmd(0b10000000);
	
	//write  "INIT OK"
	lcd_write("INIT OK");
	delay(500);
	lcd_clear();
}

void send_cmd(uint8_t pCmd)
{
	digitalWrite(pins_control[RS], 0);
	for (uint8_t i = 0; i < 8; i++)
	{
		digitalWrite(pins_data[i], (pCmd >> i) & 0b00000001);
	}
	send_pulse();
}

void send_data(uint8_t pData)
{
	digitalWrite(pins_control[RS], 1);
	for (uint8_t i = 0; i < 8; i++)
	{
		digitalWrite(pins_data[i], (pData >> i) & 0b00000001);
	}
	send_pulse();
}

void send_pulse(void)
{
	digitalWrite(pins_control[EN], 1);
	delay(10);
	digitalWrite(pins_control[EN], 0);
}

void lcd_write(uint8_t *pChar)
{
	for(uint8_t i = 0; pChar[i] != '\0'; i++)
	{
		send_data(pChar[i]);
	}
}

void lcd_setCursor(uint8_t col, uint8_t row)
{
	if (row == 0)
	{
		send_cmd(0b10000000 + col);
	}
	
	else if (row == 1)
	{
		send_cmd(0b11000000 + col);
	}
	
	else if (row == 2)
	{
		send_cmd(0b10010100 + col);
	}
	
	else
	{
		send_cmd(0b11010100 + col);
	}
} 

void lcd_clear(void)
{
	send_cmd(0b00000001); 
}

I do realize this is not really a good library, a lot of things are lacking, harcoded, and the most obvious part is the "lcd_setCursor".

Therefore, anything(I expect harsh one this time) are welcomed.

For 4 bit mode you have to update send_cmd() and send_data(). Since both functions essentially do the same, except for the RS pin, I'd write one function that can do both, and add to it a boolean asCmd parameter for selecting the right mode.

You meant something like this?

send_cmd(uint8_t pCmd, bool mode)

Actually, I am thinking of making send_cmd() available to the users, so I don't have to create functions for shifting the cursor, blinking cursor, display on/off, and a few more to list. But they still have to look up the documentation to know what value to be put in send_cmd(value).

Or maybe modify send_cmd() to accept human readable value such as send_cmd(shiftDisplayLeft), but that's assume they won't do any typo...

What do you think?

It's a matter of taste. If you write a library, you can/should provide both low and high level functions, to please all of your users.

Thanks @DrDiettrich. I agree with giving the users low level functions, it provides flexibility without the need to alter the library.

However, what's sort of way I can implement to make the user set the LCD as 8-bit or 4-bit?

I'm thinking of something like this

lcd_set4bit();
lcd_set8bit();

The downside is that it is not automatic.

See the common libraries, they offer different methods or constructors with 4 or 8 data pin numbers.

Why are you programming in C in a file with a .cpp extension? That will still invoke the C++ compiler. If you are going to program in C (uselessly), use a .c extension.

@DrDiettrich
I will see the original LCD library and try to come up with a solution.

@PaulS
Ah actually I have fixed it. But I didn't bother to edit the #1 post. I guess you must be looking at the comment "//LCDinC.cpp".