diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | instr-daemon.c | 3 | ||||
-rw-r--r-- | lcd.c | 304 | ||||
-rw-r--r-- | lcd.h | 7 | ||||
-rw-r--r-- | response.c | 4 |
5 files changed, 319 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b01906..56f5ee4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ find_package(Glib) find_package(GIO) include_directories(${GLIB_PKG_INCLUDE_DIRS}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") -add_executable(instr-daemon instr-daemon.c signalobject.c response.c i2c.c) +add_executable(instr-daemon instr-daemon.c signalobject.c response.c i2c.c lcd.c) add_executable(instr-client instr-client.c) target_link_libraries(instr-daemon gio-2.0 gobject-2.0 glib-2.0) diff --git a/instr-daemon.c b/instr-daemon.c index 21864f7..dc941b5 100644 --- a/instr-daemon.c +++ b/instr-daemon.c @@ -1,5 +1,6 @@ #include "socket-common.h" #include "response.h" +#include "lcd.h" #include <stdlib.h> #include <ctype.h> @@ -219,6 +220,8 @@ int main(int argc, char **argv) GError *error = NULL; GIOChannel* stdinChannel = NULL; + LCD_initialize(); + g_type_init (); //register stdin channel @@ -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;
+}
+
+
+
@@ -0,0 +1,7 @@ +#define Press_Change_Message "Push CHANGE to continue."
+
+
+void LCD_display_error_message(char *response);
+void LCD_clear();
+void LCD_write(int row, int col, char *LCD_string);
+void LCD_initialize(void);
@@ -1,5 +1,6 @@ #include "response.h" #include "socket-common.h" +#include "lcd.h" #include "i2c.h" #include <string.h> #include <stdlib.h> @@ -106,6 +107,9 @@ void responseCb(gpointer instance, GObject *arg1, gpointer user_data) // remove leading and trailing whitespace g_strstrip (str); + // I2C/LCD test function + LCD_display_error_message(str); + guchar status = 0; // delete me, later - FIXME // I2C test code I2C_Write (PCF8574A + Upper_Encoder_Port, 0xff); |