diff options
Diffstat (limited to 'lcd.c')
-rw-r--r-- | lcd.c | 304 |
1 files changed, 304 insertions, 0 deletions
@@ -0,0 +1,304 @@ +#include "i2c.h"
+#include "lcd.h"
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define LCD_ENABLE 0x03 /* the 4x40 LCDs have two enable lines - 0x03 enables both at the same time */
+#define LCD_DATA_RAM 128 /* display RAM, in the LCD ICs */
+#define LCD_CG_RAM 64 /* custom character RAM, in the LCD ICs */
+
+#define LCD_chars_total 160
+#define LCD_cols 40
+#define LCD_rows 4 /* 4x40 LCD */
+
+char LCD_Data[LCD_rows][LCD_cols]; /* shadow copy of LCD display in local RAM, to minimize slow I2C writes */
+
+/*** EndHeader */
+
+
+static void break_up_string (char *in_string, int N, char *str1, char *str2, char *str3)
+{
+
+#define SUBSTRING_CNT 3
+
+ int input_length;
+ int j, k, copypos;
+ int n;
+
+ char *copy_input;
+ char *p;
+
+ j=k=copypos=0;
+ input_length=strlen(in_string);
+ copy_input = g_strdup(in_string);
+
+ for (j=0; j<SUBSTRING_CNT; j++) {
+
+ char * interm_str= (char *)malloc((N+1)*sizeof(char));
+ memset(interm_str,0, (N+1)*sizeof(char));
+ for (k=0; k<N; k++) {
+ copypos++; // next symbol
+ if (copypos>input_length) {
+ break;
+ }
+ if ((*(copy_input+k)==' ')&&(copypos<input_length)) { // space found
+ //find next space
+ p=strchr(copy_input+k+1,' ');
+ if (p!=NULL) {
+ // next space is beyond N char limit for one line
+ if((p-copy_input)/sizeof(char)>=N) {
+ break;
+ }
+ } else {
+ // No more spaces. Does the last chunk of text fit?
+ if (strlen(copy_input+k+1)>N-k) {
+ break;
+ }
+ }
+ }
+ // valid character, copy to output string
+ *(interm_str+k)=*(copy_input+k);
+
+ }
+ // remove processed part from the input
+ if (copypos<=input_length) {
+ strcpy(copy_input, in_string+copypos);
+ }
+ n = strlen(interm_str);
+ for (k=n-1; k=0; k--) { //trim space
+ if (*(interm_str+k)==' ') {
+ *(interm_str+k)=0;
+ } else {
+ break;
+ }
+ }
+ switch (j) {
+ case 0:
+ strcpy(str1,interm_str);
+ break;
+ case 1:
+ strcpy(str2,interm_str);
+ break;
+ case 2:
+ strcpy(str3,interm_str);
+ break;
+ }
+ free(interm_str);
+
+ }
+
+ g_free(copy_input);
+}
+
+
+
+
+void LCD_clear()
+{
+ char i;
+ char j;
+
+ I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x00);
+ I2C_Write(PCF8574A+LCD_Port, 0x10 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x10);
+
+ /* wait 1.64ms */
+ g_usleep(1640);
+
+ for (i=0; i<4; ++i)
+ for (j=0; j<40; ++j) {
+ LCD_Data[i][j]=0;
+ }
+
+ return;
+}
+
+
+static void LCD_RAM_write(int RAM_start,int row, int col, char *LCD_string)
+{
+ /* rows: 0-3, cols: 0-39 */
+
+#define data_level 0x04
+
+ int i;
+ int cur_row, cur_col;
+ int String_length;
+ char char_out, enable_one_lcd;
+ int ram_location;
+ char last_op_a_write;
+
+ String_length=strlen(LCD_string);
+ enable_one_lcd=0x02;
+
+ last_op_a_write=0;
+ cur_row=row;
+ cur_col=col;
+
+ if (cur_row<2) {
+ enable_one_lcd=0x02;
+ } else {
+ enable_one_lcd=0x01;
+ }
+
+ /* write out the string */
+ for (i=0; i<String_length; ++i) {
+ if (cur_row<2) {
+ enable_one_lcd=0x02;
+ } else {
+ enable_one_lcd=0x01;
+ }
+
+ if (LCD_string[i]!=LCD_Data[cur_row][cur_col]) {
+ if (!last_op_a_write) {
+ /* move to new position */
+ ram_location = (cur_row & 1) * 64 + cur_col + RAM_start;
+ char_out=ram_location & 0xf0;
+ I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd);
+ I2C_Write(PCF8574A+LCD_Port, char_out);
+ char_out=ram_location << 4;
+ I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd);
+ I2C_Write(PCF8574A+LCD_Port, char_out);
+ }
+ LCD_Data[cur_row][cur_col]=LCD_string[i];
+ char_out=LCD_string[i] & 0xf0;
+ I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd | data_level);
+ I2C_Write(PCF8574A+LCD_Port, char_out | data_level);
+ char_out=LCD_string[i] << 4;
+ I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd | data_level);
+ I2C_Write(PCF8574A+LCD_Port, char_out | data_level);
+ last_op_a_write=1;
+ } else {
+ last_op_a_write=0;
+ }
+
+ ++cur_col;
+ if (cur_col==40) {
+ cur_col=0;
+ ++cur_row;
+ }
+ }
+ return;
+}
+
+
+void LCD_write(int row, int col, char *LCD_string)
+{
+ LCD_RAM_write(LCD_DATA_RAM, row, col, LCD_string);
+ return;
+}
+
+
+static void LCD_make_custom_chars()
+{
+ /* define custom LCD characters 2 and 3 (up arrow and down arrow).*/
+ /* The up arrow is stored in one LCD controller (for rows 0 and 1) */
+ /* The down arrow is stored in the other LCD controller (for rows 2 and 3) */
+ LCD_RAM_write(LCD_CG_RAM,0,16,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,0,17,"\xe");
+ LCD_RAM_write(LCD_CG_RAM,0,18,"\x15");
+ LCD_RAM_write(LCD_CG_RAM,0,19,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,0,20,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,0,21,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,0,22,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,0,23,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,2,24,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,2,25,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,2,26,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,2,27,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,2,28,"\x4");
+ LCD_RAM_write(LCD_CG_RAM,2,29,"\x15");
+ LCD_RAM_write(LCD_CG_RAM,2,30,"\xe");
+ LCD_RAM_write(LCD_CG_RAM,2,31,"\x4");
+// prove that it works - debug only
+// LCD_RAM_write(LCD_DATA_RAM,0,39,"\x2");
+// LCD_RAM_write(LCD_DATA_RAM,3,39,"\x3");
+
+ return;
+}
+
+
+void LCD_initialize(void)
+{
+ /* Wait 15ms */
+ g_usleep(15000);
+
+ I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x30);
+
+ /* wait 4.1ms */
+ g_usleep(4100);
+
+ I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x30);
+
+ /* wait 100us */
+ g_usleep(100);
+
+ I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x30);
+
+ /* wait 4.1ms */
+ g_usleep(4100);
+
+ I2C_Write(PCF8574A+LCD_Port, 0x20 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x20);
+
+ /*wait 40us */
+ g_usleep(40);
+
+ I2C_Write(PCF8574A+LCD_Port, 0x20 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x20);
+ I2C_Write(PCF8574A+LCD_Port, 0x80 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x80);
+
+ /* wait 40us */
+ g_usleep(40);
+
+ LCD_clear();
+
+ I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x00);
+ I2C_Write(PCF8574A+LCD_Port, 0x60 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x60);
+
+ /* wait 40us */
+ g_usleep(40);
+
+ I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0x00);
+ I2C_Write(PCF8574A+LCD_Port, 0xc0 | LCD_ENABLE);
+ I2C_Write(PCF8574A+LCD_Port, 0xc0);
+
+ LCD_make_custom_chars();
+
+ return;
+}
+
+
+void LCD_display_error_message(char *response)
+{
+ char row0[LCD_cols+1];
+ char row1[LCD_cols+1];
+ char row2[LCD_cols+1];
+
+ memset(row0,0,LCD_cols+1);
+ memset(row1,0,LCD_cols+1);
+ memset(row2,0,LCD_cols+1);
+
+// Error_Screen=1; //FIXME
+
+ break_up_string (response, LCD_cols, row0, row1, row2);
+
+ LCD_clear();
+ LCD_write(0,0,row0);
+ LCD_write(1,0,row1);
+ LCD_write(2,0,row2);
+ LCD_write(3,0,Press_Change_Message);
+
+ return;
+}
+
+
+
|