#include "i2c.h" #include "lcd.h" #include "globals.h" #include #include #include #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 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; jinput_length) { break; } if ((*(copy_input+k)==' ')&&(copypos=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: *str1 = g_strdup(interm_str); break; case 1: *str2 = g_strdup(interm_str); break; case 2: *str3 = g_strdup(interm_str); break; } g_free(interm_str); } g_free(copy_input); } void LCD_clear() { int i; int 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; if (!LCD_string) { return; } 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 width) { padded = g_strdup (LCD_string); padded[width] = 0; } else { padded = g_strdup_printf ("%s%*s", LCD_string, width - in_len, ""); } LCD_write(row, col, padded); g_free (padded); } void LCD_write_padded_to_end_of_line(int row, int col, char *LCD_string) { LCD_write_padded_spaces (row, col, LCD_string, LCD_cols - col - strlen (LCD_string)); } 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_extended_message(char *response, gboolean show_change_message, gboolean is_error_screen) { char *row0 = NULL; char *row1 = NULL; char *row2 = NULL; g_assert (response); if (is_error_screen) { globals.MenuStatus.Error_Screen = is_error_screen; } 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); if (show_change_message) { LCD_write(3,0,Press_Change_Message); } g_free (row0); g_free (row1); g_free (row2); return; }