/* I2C LCD Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
int LOW = 0;
int HIGH =1;
typedef uint8_t byte;
void digitalWrite(int pin, int val)
{
gpio_set_level(pin, val);
}
void delay(float d)
{
vTaskDelay(d / portTICK_PERIOD_MS);
}
// method for starting transmition - I2C protocol
void start(int d,int c,int t){
// c is the clock pin
// d is the data pin
// t is the time reference
digitalWrite(d, LOW);
delay(t/6);
digitalWrite(c, LOW);
delay(t/6);
}
// method for stoping transmition - I2C protocol
void stop(int d,int c,int t){
// c is the clock pin
// d is the data pin
// t is the time reference
digitalWrite(c, HIGH);
delay(t/6);
digitalWrite(d, HIGH);
}
// method for transmiting a bit 1 - I2C protocol
void writeOne(int d,int c,int t){
// c is the clock pin
// d is the data pin
// t is the time reference
digitalWrite(d, HIGH);
delay(t/6);
digitalWrite(c, HIGH);
delay(t/3);
digitalWrite(c, LOW);
delay(t/6);
digitalWrite(d, LOW);
}
// method for transmiting a bit 0 - I2C protocol
void writeZero(int d,int c,int t){
// c is the clock pin
// d is the data pin
// t is the time reference
digitalWrite(d, LOW);
digitalWrite(c, LOW);
delay(t/6);
digitalWrite(c, HIGH);
delay(t/3);
digitalWrite(c, LOW);
delay(t/6);
}
// method for transmiting an entire byte
void writeByte(int d,int c,int t,byte b){
// c is the clock pin
// d is the data pin
// t is the time reference
// b is the byte to be sent
// loop for transmiting the 8 bits
for(int i=8;i>=1;i--){
if((( b & (1 << (i-1) ) ) ? 1 : 0 )==0){
writeZero(d,c,t);
}
else{
writeOne(d,c,t);
}
}
// procedure for receiving the acknowledge bit from the LCD - I2C protocol
// NOTE: nothing is done with this bit, but you can verify it if you want
gpio_set_direction(d, GPIO_MODE_INPUT);
delay(t/6);
digitalWrite(c, HIGH);
delay(t/6);
digitalWrite(c, LOW);
delay(t/6);
gpio_set_direction(d, GPIO_MODE_OUTPUT);
delay(t/6);
}
// method for transmiting an entire command or data to the LCD
// NOTE: each command or data is sent in an entire start-stop I2C protocol cycle,
// but it's not mandatory
void writeCommand(int d,int c,int t,byte a,byte b){
// c is the clock pin
// d is the data pin
// t is the time reference
// a is the address of the LCD (0x4E)
// b is the byte to be sent
byte temp = b;
// sending the command or data WITHOUT to active the E (enable) line
start(d,c,t);
writeByte(d,c,t,a); // sends the address
writeByte(d,c,t,b); // sends the command or data
stop(d,c,t);
b = b | 0x04; // combining the command or data with the E (enable) line
delay(t);
// sending the command or data activating the E (enable) line
start(d,c,t);
writeByte(d,c,t,a); // sends the address
writeByte(d,c,t,b); // sends the command or data with the enable signal
stop(d,c,t);
delay(t);
// sending the command or data WITHOUT to active the E (enable) line again
start(d,c,t);
writeByte(d,c,t,a); // sends the address
writeByte(d,c,t,temp); // sends the command or data again
stop(d,c,t);
delay(t);
}
/*
Let's set the address of the LCD: it's 0x27 (00100111), but we
should send it in 7 bits (0100111) plus an 0, that indicates
a write operation, resulting in 0x4E (01001110)
*/
uint8_t ADR=0x4E;
int CLK=13; // pin 3 is set for clock
int DTA=12; // pin 4 is set for data
int TIME=1; // time reference; increase it if you want to debug the code
void lcd_task(void *pvParameter)
{
while (1) {
writeCommand(DTA,CLK,TIME,ADR,0x00); // resets the backlight anode (P3 of the PCF8574T)
delay(500);
writeCommand(DTA,CLK,TIME,ADR,0x08); // sets the backlight anode (P3 of the PCF8574T)
delay(500);
}
vTaskDelete( NULL );
}
void app_main()
{
// sets pins 3 (clock) and 4 (data) as outputs
gpio_reset_pin(CLK);
gpio_set_direction(CLK, GPIO_MODE_OUTPUT);
gpio_reset_pin(DTA);
gpio_set_direction(DTA, GPIO_MODE_OUTPUT);
// sets initial conditions of clock and data as 1 (high level)
gpio_set_level(CLK, 1);
gpio_set_level(DTA, 1);
writeCommand(DTA,CLK,TIME,ADR,0x30); // wake up, LCD!
writeCommand(DTA,CLK,TIME,ADR,0x30);
writeCommand(DTA,CLK,TIME,ADR,0x30);
writeCommand(DTA,CLK,TIME,ADR,0x20); // sets 4 bits mode... so, all commands and data should be sent in 2 parts
writeCommand(DTA,CLK,TIME,ADR,0x20); // sets 2 lines LCD and 5x8 dots
writeCommand(DTA,CLK,TIME,ADR,0x80);
writeCommand(DTA,CLK,TIME,ADR,0x00); // turns the LCD on
writeCommand(DTA,CLK,TIME,ADR,0xC0);
writeCommand(DTA,CLK,TIME,ADR,0x00); // cleans the display
writeCommand(DTA,CLK,TIME,ADR,0x10);
writeCommand(DTA,CLK,TIME,ADR,0x00); // sets Entry Mode
writeCommand(DTA,CLK,TIME,ADR,0x60);
writeCommand(DTA,CLK,TIME,ADR,0x00); // sets DDRAM address 0 in address counter. Also
writeCommand(DTA,CLK,TIME,ADR,0x20); // returns display from being shifted to original position.
// write the message - remember the need to set the backlight anode (P3 of the PCF8574T)
writeCommand(DTA,CLK,TIME,ADR,0x49); // write "H"
writeCommand(DTA,CLK,TIME,ADR,0x89);
writeCommand(DTA,CLK,TIME,ADR,0x69); // write "e"
writeCommand(DTA,CLK,TIME,ADR,0x59);
writeCommand(DTA,CLK,TIME,ADR,0x69); // write "l"
writeCommand(DTA,CLK,TIME,ADR,0xC9);
writeCommand(DTA,CLK,TIME,ADR,0x69); // write "l"
writeCommand(DTA,CLK,TIME,ADR,0xC9);
writeCommand(DTA,CLK,TIME,ADR,0x69); // write "o"
writeCommand(DTA,CLK,TIME,ADR,0xF9);
writeCommand(DTA,CLK,TIME,ADR,0x29); // write " "
writeCommand(DTA,CLK,TIME,ADR,0x09);
writeCommand(DTA,CLK,TIME,ADR,0x59); // write "W"
writeCommand(DTA,CLK,TIME,ADR,0x79);
writeCommand(DTA,CLK,TIME,ADR,0x69); // write "o"
writeCommand(DTA,CLK,TIME,ADR,0xF9);
writeCommand(DTA,CLK,TIME,ADR,0x69); // write "k"
writeCommand(DTA,CLK,TIME,ADR,0xB9);
writeCommand(DTA,CLK,TIME,ADR,0x79); // write "w"
writeCommand(DTA,CLK,TIME,ADR,0x79);
writeCommand(DTA,CLK,TIME,ADR,0x69); // write "i"
writeCommand(DTA,CLK,TIME,ADR,0x99);
writeCommand(DTA,CLK,TIME,ADR,0x29); // write "!"
writeCommand(DTA,CLK,TIME,ADR,0x19);
xTaskCreate(
&lcd_task, // task function
"lcd_backlight_task", // task name
2048, // stack size in words
NULL, // pointer to parameters
5, // priority
NULL); // out pointer to task handle
}