/* testana_out.c * test file for testing AT91RM9200 tc, deals with the Ana_out/Counter 1 for example to run 1000 loops at 60 Hz: /usr/src/ana_out/testana_out -p 16667 -w -l 1000 & # put in background, then do: /usr/src/ana_out/testana_out -v # to run the 32K ana_out ioctl */ #include #include #include #include #include #include #include #include #include #include #include #include const char* program_name; /* The name of this program. */ /* A string listing valid short options letters. */ const char* const short_options = "d:l:a:ryv"; /* An array describing valid long options. */ const struct option long_options[] = { { "device", 1, NULL, 'd' }, { "loop", 1, NULL, 'l' }, { "alarm", 1, NULL, 'a' }, { "restart", 0, NULL, 'r' }, { "delay", 0, NULL, 'y' }, { "verbose", 0, NULL, 'v' }, { NULL, 0, NULL, 0 } /* Required at end of array. */ }; struct ANA_OUT_DATA { pthread_t ana_out_thread_id; pthread_t report_thread_id; struct ana_out_alarm_light_data alarm_light_data; int loop_cnt; int delay; int fd; int alarm_light_level; pthread_mutex_t mutex; /* Protects access to value */ pthread_cond_t cond1; /* Signals change to value */ int verbose; /* be verbose? */ #define DEFAULT_INITIAL_COUNT 10 /* initial count */ const char *filename; }; struct ana_out_alarm_light_data alarm_light_lut[9] = { { { 0, 0, 0, 0, 0, 0, 0, 0, }, /* 0 / 8 */ { 0, 0, 0, 0, 0, 0, 0, 0, }, { 0, 0, 0, 0, 0, 0, 0, 0, }, }, { { 0, 0, 0, 0, 1, 0, 0, 0, }, /* 1 / 8 */ { 0, 0, 0, 0, 1, 0, 0, 0, }, { 0, 0, 0, 0, 1, 0, 0, 0, }, }, { { 1, 0, 0, 0, 1, 0, 0, 0, }, /* 2 / 8 */ { 1, 0, 0, 0, 1, 0, 0, 0, }, { 1, 0, 0, 0, 1, 0, 0, 0, }, }, { { 1, 0, 0, 1, 0, 0, 1, 0, }, /* 3 / 8 */ { 1, 0, 0, 1, 0, 0, 1, 0, }, { 1, 0, 0, 1, 0, 0, 1, 0, }, }, { { 1, 0, 1, 0, 1, 0, 1, 0, }, /* 4 / 8 */ { 1, 0, 1, 0, 1, 0, 1, 0, }, { 1, 0, 1, 0, 1, 0, 1, 0, }, }, { { 0, 1, 1, 0, 1, 1, 0, 1, }, /* 5 / 8 */ { 0, 1, 1, 0, 1, 1, 0, 1, }, { 0, 1, 1, 0, 1, 1, 0, 1, }, }, { { 1, 0, 1, 1, 1, 0, 1, 1, }, /* 6 / 8 */ { 1, 0, 1, 1, 1, 0, 1, 1, }, { 1, 0, 1, 1, 1, 0, 1, 1, }, }, { { 1, 1, 1, 1, 0, 1, 1, 1, }, /* 7 / 8 */ { 1, 1, 1, 1, 0, 1, 1, 1, }, { 1, 1, 1, 1, 0, 1, 1, 1, }, }, { { 1, 1, 1, 1, 1, 1, 1, 1, }, /* 8 / 8 */ { 1, 1, 1, 1, 1, 1, 1, 1, }, { 1, 1, 1, 1, 1, 1, 1, 1, }, }, }; struct ANA_OUT_DATA ana_out_data = { .loop_cnt = 10, .verbose = 0, /* be verbose? */ .filename = "/dev/ana_out0", .alarm_light_level = 4, .delay = 0, }; void print_usage (FILE* stream, int exit_code) { fprintf (stream, "Usage: %s options\n", program_name); fprintf (stream, " -d --device device ANA_OUT. [/dev/ana_out0]\n" " -l --loop count How many times to loop. [2]\n" " -a --alarm value Alarm light value 0-7\n" " -r --restart Restart ana_out/counter upon delay.\n" " -y --delay Delay for 1 second after 20 count.\n" " -v --verbose Print verbose messages.\n"); exit (exit_code); } #define ANA_OUT_START_CNT 1 /* one time */ unsigned int loop_cnt = ANA_OUT_START_CNT; void *ana_out_thread(struct ANA_OUT_DATA *p_data); void *report_thread(struct ANA_OUT_DATA *p_data); static int set_realtime_priority(int sched_mode) { struct sched_param schp; /* * set the process to realtime privs */ memset(&schp, 0, sizeof(schp)); schp.sched_priority = sched_get_priority_max(sched_mode); if (sched_setscheduler(0, sched_mode, &schp) != 0) { perror("sched_setscheduler"); return -1; } return 0; } int main(int argc, char **argv) { struct ANA_OUT_DATA *p_data; int next_option; unsigned int cntr; int restart = 0; int err, rc; pthread_attr_t attr2 = {0}; p_data = &ana_out_data; do { next_option = getopt_long (argc, argv, short_options, long_options, NULL); switch (next_option) { case 'd': /* -d or --device */ /* This option takes an argument, the name of the file. */ p_data->filename = optarg; break; case 'l': /* -l or --loop */ /* This option takes an argument, the loop count. */ p_data->loop_cnt = strtol (optarg, NULL, 0); break; case 'a': /* -a or --alarm */ /* This option takes an argument, the alarm in us. */ p_data->alarm_light_level = strtol (optarg, NULL, 0); break; case 'r': /* -r or --restart */ restart = 1; break; case 'y': /* -y or --delay */ p_data->delay = 1; break; case 'v': /* -v or --verbose */ p_data->verbose = 1; break; case '?': /* The user specified an invalid option. */ /* Print usage information to standard error, and exit with exit code one (indicating abonormal termination). */ print_usage (stderr, 1); break; case -1: /* Done with options. */ break; default: /* Something else: unexpected. */ abort (); } } while (next_option != -1); set_realtime_priority(SCHED_FIFO); rc = pthread_attr_init( &attr2 ); if ( rc == -1 ) { perror( "pthread_attr_init()" ) ; return( errno ) ; } rc = pthread_attr_setschedpolicy( &attr2, SCHED_FIFO ); if ( rc == -1 ) { perror( "pthread_attr_setschedpolicy()" ) ; return( errno ) ; } rc = pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED); if ( rc == -1 ) { perror( "pthread_attr_setinheritsched()" ) ; return( errno ) ; } if ((err = pthread_create (&p_data->ana_out_thread_id, &attr2, (void *) ana_out_thread, p_data)) != 0) { printf("Create error!\n"); return(err); } if ((err = pthread_create (&p_data->report_thread_id, &attr2, (void *) report_thread, p_data)) != 0) { printf("Create error!\n"); return(err); } printf("waiting for thread\n"); pthread_join( p_data->ana_out_thread_id, NULL); /* let read finish */ // pthread_join( p_data->report_thread_id, NULL); /* let report finish */ exit(0); } void *ana_out_thread(struct ANA_OUT_DATA *p_data) { unsigned int diff, cntr; int fd; struct ana_out_alarm_light_data ana_out_ioctl; struct timespec ts = { 0, 0 } ; #define ANA_OUT_START_CNT 1 /* one time */ if (p_data->verbose) printf ("ana_out test program\n"); if ((fd = open(p_data->filename, O_RDWR)) < 0) { printf ("open failed %s\n", p_data->filename); return; } for (cntr = 0; cntr < p_data->loop_cnt; cntr++) { memcpy (&p_data->alarm_light_data, &alarm_light_lut[p_data->alarm_light_level], sizeof (alarm_light_lut[0])); if (p_data->verbose) printf ("alarm_light_level = %d data = %d\n", p_data->alarm_light_level, p_data->alarm_light_data.alarm_light_red_pwm[0]); if (ioctl (fd, ANA_OUT_ALARM_LIGHT, &p_data->alarm_light_data)) /* call setup, used to get init crtr val */ { perror ("ANA_OUT_ALARM_LIGHT failed"); close (fd); return; } if (p_data->delay) /* delay in seconds */ { if (p_data->verbose) printf("waiting..."); ts.tv_sec = p_data->delay; nanosleep( &ts, NULL) ; } if (++p_data->alarm_light_level > 8) p_data->alarm_light_level = 0; } close (fd); return; } void *report_thread(struct ANA_OUT_DATA *p_data) { if (p_data->verbose) printf ("report_thread\n"); while (1) { /* delay in nanoseconds */ struct timespec ts = { 2, 0 } ; if (p_data->verbose) printf("waiting..."); nanosleep( &ts, NULL) ; } return; }