Solved

Serial communications

Posted on 2012-03-21
8
311 Views
Last Modified: 2012-06-27
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);
}
0
Comment
Question by:sargent240
  • 4
  • 4
8 Comments
 
LVL 7

Expert Comment

by:tampnic
Comment Utility
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
 

Author Comment

by:sargent240
Comment Utility
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
 
LVL 7

Expert Comment

by:tampnic
Comment Utility
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
 

Author Comment

by:sargent240
Comment Utility
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:sargent240
Comment Utility
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
 
LVL 7

Accepted Solution

by:
tampnic earned 500 total points
Comment Utility
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
 

Author Closing Comment

by:sargent240
Comment Utility
Timer is not going to work.  Going another direction.  However thanks
0
 
LVL 7

Expert Comment

by:tampnic
Comment Utility
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

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now