Thread: RS232 input/output help needed

  1. #1
    Registered User
    Join Date
    May 2011
    Posts
    3

    RS232 input/output help needed

    Hi, I'm new at programming and new at Linux. It happened so, that I'm working on a project where i thought I'd just edit already written program and have the wished result. Well what do you know! It isn't as easy as I assumed I've got a code of an internet radio tuner, but I want to make it send output (status1, status2 and status3 text in code) character by character (1 second interval between characters) to my serial RS232 port. And I need the program to react (change preset) to input from RS232 serial port. So when I connect my serial LCD and keypad to computer RS232 i get external user interface for the program. In my mind it sounded way easier than it seems to be to me. The OS is Ubuntu. I've got this code:

    Code:
    #include <gtk/gtk.h>
    #include <glade/glade.h>
    #include <glib/gthread.h>
    #include <stdlib.h>
    #include <string.h>
    #include "bass.h"
    
    // path to glade file
    #ifndef GLADE_PATH
    #define GLADE_PATH ""
    #endif
    
    GladeXML *glade;
    GtkWidget *win=0;
    GThread *cthread=0;
    guint prebuftimer;
    HSTREAM chan;
    
    const char *urls[10]={ // preset stream URLs
    	"http://servers.internet-radio.org.uk/tools/playlistgenerator/?u=http://cp.internet-radio.org.uk:15634/listen.pls&t=.pls",
    	"http://84.32.194.146/crfm.aac.m3u",
    	"http://84.32.194.146:80/crfm.aac",
    	"http://somafm.com/tags.pls","http://somafm.com/tags32.pls",
    	"http://somafm.com/secretagent.pls","http://somafm.com/secretagent24.pls"
    };
    
    char proxy[100]=""; // proxy server
    
    // display error messages
    void Error(const char *es)
    {
    	GtkWidget *dialog=gtk_message_dialog_new(GTK_WINDOW(win),GTK_DIALOG_DESTROY_WITH_PARENT,
    		GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
    	gtk_dialog_run(GTK_DIALOG(dialog));
    	gtk_widget_destroy(dialog);
    }
    
    #define GetWidget(id) glade_xml_get_widget(glade,id)
    
    void WindowDestroy(GtkObject *obj, gpointer data)
    {
    	gtk_main_quit();
    }
    
    void gtk_label_set_text_8859(GtkLabel *label, const gchar *text)
    {
    	gsize s;
    	char *utf=g_convert(text,-1,"UTF-8","ISO-8859-1",NULL,&s,NULL);
    	if (utf) {
    		gtk_label_set_text(label,utf);
    		g_free(utf);
    	} else
    		gtk_label_set_text(label,text);
    }
    
    // update stream title from metadata
    void DoMeta()
    {
    	GtkLabel *label=GTK_LABEL(GetWidget("status1"));
    	const char *meta=BASS_ChannelGetTags(chan,BASS_TAG_META);
    	if (meta) { // got Shoutcast metadata
    		char *p=strstr(meta,"StreamTitle='");
    		if (p) {
    			p=strdup(p+13);
    			strchr(p,';')[-1]=0;
    			gtk_label_set_text_8859(label,p);
    			free(p);
    		}
    	} else {
    		meta=BASS_ChannelGetTags(chan,BASS_TAG_OGG);
    		if (meta) { // got Icecast/OGG tags
    			const char *artist=NULL,*title=NULL,*p=meta;
    			for (;*p;p+=strlen(p)+1) {
    				if (!strncasecmp(p,"artist=",7)) // found the artist
    					artist=p+7;
    				if (!strncasecmp(p,"title=",6)) // found the title
    					title=p+6;
    			}
    			if (artist) {
    				char text[100];
    				snprintf(text,sizeof(text),"%s - %s",artist,title);
    				gtk_label_set_text(label,text);
    			} else if (title)
    				gtk_label_set_text(label,title);
    		}
        }
    }
    
    void CALLBACK MetaSync(HSYNC handle, DWORD channel, DWORD data, void *user)
    {
    	gdk_threads_enter();
    	DoMeta();
    	gdk_threads_leave();
    }
    
    void CALLBACK EndSync(HSYNC handle, DWORD channel, DWORD data, void *user)
    {
    	gdk_threads_enter();
    	gtk_label_set_text(GTK_LABEL(GetWidget("status1")),"");
    	gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"not playing");
    	gtk_label_set_text(GTK_LABEL(GetWidget("status3")),"");
    	gdk_threads_leave();
    }
    
    void CALLBACK StatusProc(const void *buffer, DWORD length, void *user)
    {
    	if (buffer && !length) {
    		gdk_threads_enter();
    		gtk_label_set_text(GTK_LABEL(GetWidget("status3")),buffer); // display connection status
    		gdk_threads_leave();
    	}
    }
    
    gboolean PrebufTimerProc(gpointer data)
    { // monitor prebuffering progress
    	DWORD progress=BASS_StreamGetFilePosition(chan,BASS_FILEPOS_BUFFER)
    		*100/BASS_StreamGetFilePosition(chan,BASS_FILEPOS_END); // percentage of buffer filled
    	if (progress>75 || !BASS_StreamGetFilePosition(chan,BASS_FILEPOS_CONNECTED)) { // over 75% full (or end of download)
    		{ // get the broadcast name and URL
    			const char *icy=BASS_ChannelGetTags(chan,BASS_TAG_ICY);
    			if (!icy) icy=BASS_ChannelGetTags(chan,BASS_TAG_HTTP); // no ICY tags, try HTTP
    			if (icy) {
    				for (;*icy;icy+=strlen(icy)+1) {
    					if (!strncasecmp(icy,"icy-name:",9))
    						gtk_label_set_text_8859(GTK_LABEL(GetWidget("status2")),icy+9);
    					if (!strncasecmp(icy,"icy-url:",8))
    						gtk_label_set_text_8859(GTK_LABEL(GetWidget("status3")),icy+8);
    				}
    			} else
    				gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"");
    		}
    		// get the stream title and set sync for subsequent titles
    		DoMeta();
    		BASS_ChannelSetSync(chan,BASS_SYNC_META,0,&MetaSync,0); // Shoutcast
    		BASS_ChannelSetSync(chan,BASS_SYNC_OGG_CHANGE,0,&MetaSync,0); // Icecast/OGG
    		// set sync for end of stream
    		BASS_ChannelSetSync(chan,BASS_SYNC_END,0,&EndSync,0);
    		// play it!
    		BASS_ChannelPlay(chan,FALSE);
    		return FALSE; // stop monitoring
    	} else {
    		char text[20];
    		sprintf(text,"buffering... %d%%",progress);
    		gtk_label_set_text(GTK_LABEL(GetWidget("status2")),text);
    		return TRUE; // continue monitoring
    	}
    }
    
    void *OpenURL(char *url)
    {
    	g_source_remove(prebuftimer); // stop prebuffer monitoring
    	BASS_StreamFree(chan); // close old stream
    	gdk_threads_enter();
    	gtk_label_set_text(GTK_LABEL(GetWidget("status1")),"");
    	gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"connecting...");
    	gtk_label_set_text(GTK_LABEL(GetWidget("status3")),"");
    	gdk_threads_leave();
    	if (!(chan=BASS_StreamCreateURL(url,0,BASS_SAMPLE_FLOAT|BASS_STREAM_STATUS|BASS_STREAM_AUTOFREE,StatusProc,0))) {
    		gdk_threads_enter();
    		gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"not playing");
    		Error("Can't play the stream");
    		gdk_threads_leave();
    	} else
    		prebuftimer=g_timeout_add(50,PrebufTimerProc,NULL); // start prebuffer monitoring
    	cthread=0;
    	return NULL;
    }
    
    void PresetClicked(GtkButton *obj, gpointer data)
    {
    	if (cthread) { // already connecting
    		// beep!
    	} else {
    		const char *url;
    		const gchar *objname=gtk_widget_get_name(GTK_WIDGET(obj));
    		if (!strcmp(objname,"customopen")) { // play a custom URL
    			url=gtk_entry_get_text(GTK_ENTRY(GetWidget("customurl")));
    		} else { // play a preset
    			int preset=atoi(objname+6)-1; // get preset from button name ("presetX")
    			url=urls[preset];
    		}
    		strcpy(proxy,gtk_entry_get_text(GTK_ENTRY(GetWidget("proxyurl")))); // get proxy server
    		// open URL in a new thread (so that main thread is free)
    		cthread=g_thread_create(OpenURL,url,FALSE,NULL);
    	}
    }
    
    void ProxyDirectToggled(GtkToggleButton *obj, gpointer data)
    {
    	if (obj->active)
    		BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,NULL); // disable proxy
    	else
    		BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,proxy); // enable proxy
    }
    
    int main(int argc, char* argv[])
    {
    	g_thread_init(NULL);
    	gdk_threads_init();
    	gtk_init(&argc,&argv);
    
    	// check the correct BASS was loaded
    	if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
    		Error("An incorrect version of BASS was loaded");
    		return 0;
    	}
    
    	// initialize default output device
    	if (!BASS_Init(-1,44100,0,NULL,NULL)) {
    		Error("Can't initialize device");
    		return 0;
    	}
    
    	BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST,1); // enable playlist processing
    	BASS_SetConfig(BASS_CONFIG_NET_PREBUF,0); // minimize automatic pre-buffering, so we can do it (and display it) instead
    	BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,proxy); // setup proxy server location
    
    	// initialize GUI
    	glade=glade_xml_new(GLADE_PATH"netradio.glade",NULL,NULL);
    	if (!glade) return 0;
    	win=GetWidget("window1");
    	if (!win) return 0;
    	glade_xml_signal_autoconnect(glade);
    
    	gdk_threads_enter();
    	gtk_main();
    	gdk_threads_leave();
    
    	BASS_Free();
    
        return 0;
    }
    I know I should add some function like this to open serial port:

    Code:
        #include <stdio.h>   /* Standard input/output definitions */
        #include <string.h>  /* String function definitions */
        #include <unistd.h>  /* UNIX standard function definitions */
        #include <fcntl.h>   /* File control definitions */
        #include <errno.h>   /* Error number definitions */
        #include <termios.h> /* POSIX terminal control definitions */
    
        /*
         * 'open_port()' - Open serial port 1.
         *
         * Returns the file descriptor on success or -1 on error.
         */
    
        int main;
        open_port(void)
        {
          int fd; /* File descriptor for the port */
    
    
          fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
          if (fd == -1)
          {
           /*
    	* Could not open the port.
    	*/
    
    	perror("open_port: Unable to open /dev/ttyS0 - ");
          }
          else
    	fcntl(fd, F_SETFL, 0);
               return (fd);
        }
    Plus something more to write to serial port and read from it. I found something about kbhit command, but it seems to be on some special library that's got something complicated about it. I guess it would be too much to expect somebody to give me the edited version of the code, but any information, links, hints or wisdom sharing will be appreciated.

  2. #2
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    Your not going to get much help from anyone, by posting lines and lines of code you found somewhere and saying little more than "it's not working for me".
    We need to know very specifically what isn't working, how would otherwise expect it to, etc.. How can we help you, if you don't even know what's going on you yourself?

  3. #3
    Registered User
    Join Date
    May 2011
    Posts
    3
    I guess you misunderstood me. The code for the internet radio tuner works perfectly. I just need to edit it so i'd be able to control and see the output via RS232.
    The question is very easy. Maybe even too easy for such forum. How should I edit this code?
    Help me with syntax (what do the "void", "main" and similar commands mean? How is the function created, where do I put it, how do I call and address it). Internet is full of tutorials, but the ones I tried were worthless, so maybe you could help me find something or just answer the question.
    I also need help to find required functions to send output to RS232 (this should be some kind of loop which would output character by character) and control it using RS232 keypad.
    I hope I made the question understandable. If not, feel free to complain, I'll try to explain it in some other way.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > So when I connect my serial LCD and keypad to computer RS232
    So do you have the spec's for this device? Say a link.

    Before you try to use this inside the existing program, you need to make a prototype code so you can see exactly what to do.

    That is, you need two programs which basically do
    Code:
    int main ( ) {
      char *msg = "hello";
      // a bit of code here, which results in "hello" displayed on the LCD
      return 0;
    }
    Code:
    int main ( ) {
      char ch;
      // a bit of code here, which reads a char from the keypad
      printf("Got char %d(%c) from the keypad\n", ch, ch );
      return 0;
    }
    When you know how to do these things, the next steps will be a lot easier.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    May 2011
    Posts
    3
    Ok, it was a good advice. I get less error messages, when making small program, so it gives hope someday everything may work I started on LCD program. I managed to build something that looks like a program code:

    Code:
    #include <stdio.h>   /* Standard input/output definitions */
        #include <string.h>  /* String function definitions */
        #include <unistd.h>  /* UNIX standard function definitions */
        #include <fcntl.h>   /* File control definitions */
        #include <errno.h>   /* Error number definitions */
        #include <termios.h> /* POSIX terminal control definitions */
    
        
    
    	int main ( ) {
      char *msg = "hello";
      open_port();
      write(fd, msg);	 // 13 line
    return 0;
    }
    	void write(int fd, char msg) {  // 16 line
    	int *n = 0;
    	n = write(fd, msg);    // 18 line.  "hello" displayed on the LCD
        if (n < 0)
          fputs("write() of 4 bytes failed!\n", stderr);  
    
    }
         /*
         * 'open_port()' - Open serial port 1.
         *
         * Returns the file descriptor on success or -1 on error.
         */
        int
        open_port(void)
        {
          int fd; /* File descriptor for the port */
    
    
          fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
          if (fd == -1)
          {
           /*
    	* Could not open the port.
    	*/
    
    	perror("open_port: Unable to open /dev/ttyS0 - ");
          }
          else
    	fcntl(fd, F_SETFL, 0);
               return (fd);
        }
    When i try to make it i get errors:

    output.c: In function ‘main’:
    output.c:13: error: ‘fd’ undeclared (first use in this function)
    output.c:13: error: (Each undeclared identifier is reported only once
    output.c:13: error: for each function it appears in.)
    output.c:13: error: too few arguments to function ‘write’
    output.c: At top level:
    output.c:16: error: conflicting types for ‘write’
    /usr/include/unistd.h:363: note: previous declaration of ‘write’ was here
    output.c: In function ‘write’:
    output.c:18: error: void value not ignored as it ought to be

    So how come the 'fd' variable is undeclared? It should have a value sent from open-port function. Am I wrong?

    How do I address the 'write' function?

    And i don't get the last error..

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    The fd in open_port() is only local to that function.

    You return a value, so in main, you should also have
    Code:
    int fd = open_port();
    if ( fd > 0 ) {
        write(fd, msg);	
    }
    Also, you need to concentrate on indentation as well.
    SourceForge.net: Indentation - cpwiki
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    Quote Originally Posted by peikis View Post
    Code:
    	void write(int fd, char msg) {  // 16 line
    	int *n = 0;
    	n = write(fd, msg);    // 18 line.  "hello" displayed on the LCD
        if (n < 0)
          fputs("write() of 4 bytes failed!\n", stderr);  
    
    }
    You include write() already (from unistd.h), so you can't declare it again, your function needs a new name. Also, the value you read from write(), isn't int* (which is a pointer to an int), it returns just plain int.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. program needed to control output on lpt1 port
    By thegadgitman in forum C++ Programming
    Replies: 2
    Last Post: 07-06-2010, 05:45 AM
  2. Replies: 1
    Last Post: 09-24-2009, 01:28 AM
  3. Input help needed
    By blindleaf in forum C Programming
    Replies: 5
    Last Post: 04-08-2003, 06:22 PM
  4. Help needed: Output to Parallel port.
    By Ingsy in forum C Programming
    Replies: 4
    Last Post: 10-10-2001, 12:06 PM