Serial communications

This is a little C routine I use to read midi info from a keyboard.  I need an idea as to how I can get out of the loop that is reading the file.  Midi does not send an end of  file or end of string character so I need to do it somehow with the stroke of a key on the keyboard.  I remember in the old days using something like kbhit() but I can't find any of the h files needed.  Any Ideas?



#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>

int main() {
 
 const char FILE_NAME[] = "/dev/midi1";
 
int count = 0; /* number of characters seen */
FILE *in_file; /* input file */

int ch = 0;

in_file = fopen(FILE_NAME, "r");
if (in_file == NULL) {
  printf("Cannot open %s\n", FILE_NAME);
exit(8);
}

while (1) {
  ch = fgetc(in_file);
  if (ch != 248 ) {
    if ( ch != 254 ) {
      printf("%i ", ch);
      ++count;
      if (count == 40 ) {count=0; printf("\n\r"); break;}
    }
  }
}
//if (ch == EOF) {
//  break;
//}


printf("Number of characters in %s is %d\n",
FILE_NAME, count);

fclose(in_file);
return (0);
}
sargent240Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

tampnicCommented:
If I remember correctly, though its twenty years since I looked at anything musical in depth, a MIDI byte is 10 bits long - how can you read the MIDI signals with fgetc() ? Is the hardware stripping the first and last bits out for you?

I wouldn't recommend keyboard polling in the same thread as a timing-critical section like responding to MIDI data - why not start another thread and wait for a key press in that? kbhit() comes from conio.h on Borland compilers.

Cheers,
   Chris
0
sargent240Author Commented:
Chris

I store the style, voice, tempo and transposition it a memory register on the keyboard.  When I select that register on the keyboard it transmits the same info that it sends to the instrument as though it were programming another keyboard.  I will pick up the data, which can have as many as 80 hex values, and store it in a data file.  I can then duplicate the settings in the keyboard from the computer at any time in the future.  The data comes in a matter of milliseconds but I never never know the number values being sent so I would like to send the values and a second or two later strike a key on the keyboard and break out of the loop.  I tried kbhit() but when I include conio.h it cannot be found.  I am using Linux and gcc.
0
tampnicCommented:
OK - so its settings and not note messages.

I am assuming that your fgetc() call sits and waits while there is no data - and you can't tell when the data has stopped as an EOF is not sent. Why check for a keyboard hit - if you are *SURE* the data will be there within a couple of seconds one strategy could be

1) create a timer
2) fork a process to read the data (start the timer when the first byte gets read)
3) close files and kill the forked process when the timer reaches two seconds.

Alternatively

1) fork a process to read the data
2) wait for a key press in the parent process with fgetc(stdin) or getchar()
3) close files and kill the forked process when the key is hit

Alternatively

Use select() http://linux.die.net/man/2/select instead of fgetc() to read /dev/midi1. select() requires a file descriptor so use fileno(in_file) to get that. You can specify a timeout with select() so set it as two seconds and exit on the timeout once you have received data.

Cheers,
   Chris
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

sargent240Author Commented:
Chris,

I added a timer I found but am having trouble compiling it.  The error I get is:

midiio.c:36:29: error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
midiio.c:44:31: error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token

Line 36 and 44 are:

int SetTimer(struct timeval &tv, time_t sec)
int CheckTimer(struct timeval &tv, time_t sec)

The complete code follows.  Any help there? Thanks!


#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>


/* Key pressed ? */
int count = 0;

int  kbhit  (void)  {
  struct timeval  tv;
  fd_set          read_fd;
  /* Do not wait at all, not even a microsecond */
  tv.tv_sec  = 0;
  tv.tv_usec = 0;

  /* Must be done first to initialize read_fd */
  FD_ZERO(&read_fd);

  /* Makes select() ask if input is ready;  0 is file descriptor for stdin */
  FD_SET(0, &read_fd);

  /* The first parameter is the number of the largest fd to check + 1 */
  if  (select(1, &read_fd,
                 NULL,         /* No writes        */
                 NULL,         /* No exceptions    */
                 &tv)  == -1)
    return(0);                 /* an error occured */

  /* read_fd now holds a bit map of files that are readable. */
  /* We test the entry for the standard input (file 0).      */
  return(FD_ISSET(0, &read_fd)  ?  1  :  0);
}

 
int SetTimer(struct timeval &tv, time_t sec)
{
    gettimeofday(&tv,NULL);
    tv.tv_sec+=sec;
 
    return 1;
}
 
int CheckTimer(struct timeval &tv, time_t sec)
{
    struct timeval ctv;
    gettimeofday(&ctv,NULL);
 
    if( (ctv.tv_sec &gt; tv.tv_sec) )
    {
        gettimeofday(&tv,NULL);
        tv.tv_sec+=sec;
        return 1;
    }
    else
        return 0;
}


int main() {

    struct timeval tv;
    SetTimer(tv,5); //set up a delay timer
 
 const char FILE_NAME[] = "/dev/midi1";
 char str[500];
//int count = 0; /* number of characters seen */
FILE *in_file; /* input file */

int ch = 0;

in_file = fopen(FILE_NAME, "r");
if (in_file == NULL) {
  printf("Cannot open %s\n", FILE_NAME);
exit(8);
}

while (1) {
  if (CheckTimer(tv,5)==1) break;
  ch = fgetc(in_file);
  if (ch != 248 ) {
    if ( ch != 254 ) {
      printf("%i ", ch);
      ++count;
    }
  }
//        if  (kbhit()) { printf("count = %i ", count ); break; }

}

printf("Number of characters in %s is %d\n",
FILE_NAME, count);

fclose(in_file);
return (0);
}
0
sargent240Author Commented:
Oh, I messed up!  the code in my last post has some c++ code in it and that is most likely where the problem is.  I have been looking around for some timer code for c but can't seem to put my hand on some.  Having not messed around with c for about 17 years I'm struggling a bit.  Can you direct me to a timer routine or can you suggest how to change what I have.

Thanks! - Al
0
tampnicCommented:
timer_create() http://linux.die.net/man/3/timer_create is a POSIX function for creating timers. It sends a signal to the process when the timer expires so you have to write a signal handler. I'm not sure if the signal handler will be called while fgetc() is blocking though, so YMMV with this function.

Here is a link to a little ANSI C code snippet showing some simple timing using time() and difftime() to check elapsed. http://www.tek-tips.com/viewthread.cfm?qid=72974

I also found this  ... http://ubuntuforums.org/showthread.php?t=936816 The last code snippet shows use of select() with a timeout of zero to replace an fgetc() call which blocks. The issues are applicable to your situation I think.

Cheers,
   Chris
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sargent240Author Commented:
Timer is not going to work.  Going another direction.  However thanks
0
tampnicCommented:
I gave you some timer functions because that's what you asked for - I should have said that personally I would be writing the app to use select() to read from the port.

Cheers,
   Chris
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.