Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Related Pages  

counter.c

00001 /***************************************************************************
00002                           counter.c  -  description
00003 */
00004 
00011 /***************************************************************************
00012                              -------------------
00013     begin                : Tue Dec 30 2003
00014     copyright            : (C) 2003 by NZG
00015     email                : ngustavson@emacinc.com
00016  ***************************************************************************/
00017 
00018 /***************************************************************************
00019  *                                                                         *
00020  *   This program is free software; you can redistribute it and/or modify  *
00021  *   it under the terms of the GNU General Public License as published by  *
00022  *   the Free Software Foundation; either version 2 of the License, or     *
00023  *   (at your option) any later version.                                   *
00024  *                                                                         *
00025  ***************************************************************************/
00026 
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <sys/ioctl.h>
00031 #include <unistd.h>
00032 #include <sys/types.h>
00033 #include <asm/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 #include <signal.h>
00037 #include <sched.h>
00038 #include <sys/resource.h>
00039 #include <sys/io.h>
00040 #include <E12user.h>
00041 #include <packet.h>
00042 #include <coprocessor.h>
00043 #include <counter.h>
00044 #include <curses.h>
00045 #include <form.h>
00046 
00047 //#define COLOR_FIELDS  uncomment this to display the fields in color
00048 #define COLOR_FORE COLOR_BLACK
00049 #define COLOR_BACK COLOR_GREEN
00050 
00051 
00053 #define ARGCHECK(num){if(argc<=num){printf("invalid number of arguements\n");help();return -1;}}
00054 
00055 #define OPENDEV(filed,dev){if((filed = open(dev, O_RDWR))<=0){printf("couldn't open %s\n",dev);return -1;}}
00056 
00057 /*here are some graphics locations*/
00058 
00060 #define YSTART 4
00061 
00062 #define HEADER_Y YSTART-1
00063 
00064 #define FIELDSEP 7
00065 
00066 #define FIELDNUM 6
00067 
00069 enum FIELDNUMBERS {COUNT,RELOAD,TRIG,FLAG,ZERO,FREQ};
00070 
00071 
00072 /*field locations*/
00073 #define NUM_X      3 + FIELDSEP
00074 #define COUNT_X  NUM_X + FIELDSEP
00075 #define RELOAD_X   COUNT_X + FIELDSEP
00076 #define TRIG_X      RELOAD_X + FIELDSEP
00077 #define FLAG_X     TRIG_X + FIELDSEP
00078 #define ZERO_X    FLAG_X + FIELDSEP
00079 #define FREQ_X    ZERO_X + FIELDSEP
00080 #define FIRST_FIELD COUNT_X
00081 
00083 #define ARRAYCALC (channel*FIELDNUM + fieldnum)  //array element number calculation
00084 
00085 /*coordinates for extra messages*/
00086 #define MESSAGE_Y  (YSTART+COUNTNUM + 2)
00087 #define MESSAGE_X  0
00088 
00089 /*global variables for saving the location of the cursor*/
00090 int current_y,current_x;
00091 #define CURSEMESSAGE(fmt, args...) {getsyx(current_y,current_x);mvprintw(MESSAGE_Y,MESSAGE_X,fmt, ## args);setsyx(current_y,current_x);}
00092 
00093 
00095 volatile int modified;
00097 FIELD *counter_field[COUNTNUM*FIELDNUM+1];//+1 required for null terminated list
00099 FORM *counter_form;
00101 int global_fd;
00103 Cop_Data *Cop;
00104 
00106 const char *trig_strings[] = {"       ","rise   ","fall   ","any    ",NULL};
00108 const char *flag_strings[] = {"       ","__N    ","_R_    ","_RN    ","S__    ","S_N    ","SR_    ","SRN    ",NULL};
00109 
00110 
00111 
00119 static int indexenum(const char *enumptr, const char **fieldptr)
00120 {
00121 int index;
00122 
00123 for(index=0;index<10;index++)
00124 {
00125 if(!(strcmp(enumptr,fieldptr[index])))
00126   return index;
00127 }
00128 return 0;
00129 }
00130 
00131 /*Destroy the form
00132 destroys the global forms created at initialization
00133 */
00134 static void destroyform()
00135 {
00136 int channel,fieldnum;
00137 FORM *form = counter_form;
00138 
00139 unpost_form(form);
00140 free_form(form);
00141 
00142 
00143 for(channel=0;channel<COUNTNUM;channel++)
00144   for(fieldnum=0;fieldnum<FIELDNUM;fieldnum++)
00145     free_field(counter_field[ARRAYCALC]);
00146 
00147 endwin();
00148 }
00149 
00153 static int help(void)
00154 {
00155 const char *help_table = "**********************************************
00156 *e12count                                    *
00157 *Nathan Z. Gustavson                         *
00158 *Emac.inc                                    *
00159 *"__DATE__"                                 *
00160 *usage:                                      *
00161 *e12count device                             *
00162 *ex                                          *
00163 *e12count /dev/37e12                         *
00164 **********************************************\n";
00165 printf("%s",help_table);
00166 return 0;
00167 }
00168 
00173 static void field_commit_change(FORM *form)
00174 {
00175 FIELD *field =  current_field(form);
00176 int index =  field_index(field);
00177 int counter = index/FIELDNUM;
00178 int fieldnum = index%FIELDNUM;
00179 int fd = global_fd;
00180 //void *dataptr = field_arg(field);
00181 char *dataptr = field_buffer(field,0);
00182 int count;
00183 countconfig *oldconfig = &Cop->counter_config[counter];
00184 int trigger,threshold,flags;
00185 
00186 if(!modified)//no change to this field, just exit
00187   return;
00188 
00189 switch(fieldnum)
00190   {
00191     case COUNT:
00192     count = atoi(dataptr);
00193     E12_CounterLoad(fd, counter,count, Cop);
00194     break;
00195 
00196     //change to the reload(threshold) value, call E12_Count config, pass other variables from the shadow
00197     case RELOAD:
00198     threshold = atoi(dataptr);
00199     E12_CountConfig(fd, counter, oldconfig->trigger, threshold,oldconfig->flags,Cop);
00200     break;
00201 
00202     //change the trigger value, this program starts and stops the counter based on whether the trigger is enabled
00203     case TRIG:
00204     trigger = indexenum(dataptr, trig_strings);
00205     E12_CountConfig(fd, counter, trigger, oldconfig->threshold,oldconfig->flags,Cop);
00206     if(trigger)
00207       E12_CountCommand(fd,counter, ICSTART);
00208     else
00209       E12_CountCommand(fd, counter,ICSTOP);
00210     CURSEMESSAGE("trigger changed to %u\n",trigger);
00211     break;
00212 
00213      //change to the flag value, call E12_Count config, pass other variables from the shadow
00214     case FLAG:
00215     flags  =  indexenum(dataptr, flag_strings);
00216     E12_CountConfig(fd, counter, oldconfig->trigger, oldconfig->threshold,flags,Cop);
00217     CURSEMESSAGE("flags changed to %u\n",flags);
00218     break;
00219   }
00220 
00221 modified=0; //field has been updated
00222 
00223 }
00224 
00225 /*Initialize the Form
00226 This function sets up the form that is used to control the counters
00227 */
00228 static int InitForm()
00229 {
00230 int channel,fieldnum;
00231 /* Initialize curses */
00232 initscr();
00233 start_color();
00234 cbreak();
00235 noecho();
00236 keypad(stdscr, TRUE);
00237 //halfdelay(1);
00238 nodelay(stdscr, TRUE);
00239 
00240 modified=0; //flag indicating a change has happened to a field, and a commit change is pending.
00241     /* Initialize the fields */
00242 
00243 init_pair(1, COLOR_FORE, COLOR_BACK);
00244 init_pair(2, COLOR_FORE, COLOR_BACK);
00245 
00246 for(channel=0;channel<(COUNTNUM);channel++)
00247 {
00248   for(fieldnum=0;fieldnum<(FIELDNUM);fieldnum++)
00249     {
00250     counter_field[ARRAYCALC] = new_field(1, FIELDSEP, YSTART+channel, FIRST_FIELD+(fieldnum*FIELDSEP), 0, 0);
00251      /* Set field options */
00252 
00253 #ifdef COLOR_FIELDS
00254     set_field_fore(counter_field[ARRAYCALC], COLOR_PAIR(1));
00255     set_field_back(counter_field[ARRAYCALC], COLOR_PAIR(2));
00256 #endif
00257     set_field_back(counter_field[ARRAYCALC], A_UNDERLINE);  /* Print a line for the option  */
00258     field_opts_off(counter_field[ARRAYCALC], O_AUTOSKIP);   /* Don't go to next field when this */
00259 
00260     switch(fieldnum)
00261     {
00262     case COUNT:
00263     set_field_type(counter_field[ARRAYCALC],          /* field to alter */
00264                    TYPE_INTEGER,          /* type to associate */
00265                    0,           /* # places to zero-pad to */
00266                    0, 65535);   /* valid range */
00267     break;
00268 
00269     case RELOAD:
00270     set_field_type(counter_field[ARRAYCALC],          /* field to alter */
00271                    TYPE_INTEGER,          /* type to associate */
00272                    0,           /* # places to zero-pad to */
00273                    0, 65535);   /* valid range */
00274     break;
00275 
00276     case TRIG:
00277     set_field_type(counter_field[ARRAYCALC],          /* field to alter */
00278                    TYPE_ENUM,          /* type to associate */
00279                    trig_strings,           /* # valid TRIG strings*/
00280                    0, 0);
00281     break;
00282     case FLAG:
00283     set_field_type(counter_field[ARRAYCALC],          /* field to alter */
00284                    TYPE_ENUM,          /* type to associate */
00285                    flag_strings,           /* # valid FLAG strings */
00286                    0, 0);
00287     break;
00288 
00289     }
00290 
00291 
00292     }
00293 
00294 }
00295 counter_field[COUNTNUM*FIELDNUM+1] = NULL;
00296 
00297 /* Create the form and post it */
00298 counter_form = new_form(counter_field);
00299 set_field_term(counter_form, field_commit_change);
00300 post_form(counter_form);
00301 refresh();
00302 
00303 mvprintw(HEADER_Y, NUM_X, "count");
00304 mvprintw(HEADER_Y, COUNT_X, "value");
00305 mvprintw(HEADER_Y, RELOAD_X, "load ");
00306 mvprintw(HEADER_Y, TRIG_X, "trig ");
00307 mvprintw(HEADER_Y, FLAG_X, "flags");
00308 mvprintw(HEADER_Y, ZERO_X, "zeros");
00309 mvprintw(HEADER_Y, FREQ_X, "freq ");
00310 
00311 for(channel=0;channel<(COUNTNUM);channel++)
00312   mvprintw(YSTART+channel, NUM_X+2, "%u",channel);
00313 
00314 refresh();
00315 
00316 set_current_field(counter_form, counter_field[0]); /* Set focus to the colored field */
00317 
00318 return 0;
00319 }
00320 
00325 static int handlecrossing(Cop_Data *Cop)
00326 {
00327 int channel;
00328 int fieldnum;
00329 int freq = 0;
00330 char freqstring[FIELDSEP+1];
00331 char zerostring[FIELDSEP+1];
00332 
00333 for(channel=0;channel<COUNTNUM;channel++)
00334 {
00335   if(Cop->parsemask.zero&(1<<channel))
00336     {
00337       CURSEMESSAGE("channel = %u\nlaststamp=%lu\ntimestamp=%lu\nlaststart =%lu\nstart = %u\n",channel,Cop->counter_data[channel].laststamp,Cop->counter_data[channel].timestamp,Cop->counter_data[channel].laststart,Cop->counter_data[channel].countstart);
00338       if(Cop->counter_data[channel].zerocross)//if this is a zerocrossing and not the initial timestamp
00339         freq = E12_CounterCalcFreq(channel, Cop);
00340       sprintf(freqstring,"%u",freq);
00341       fieldnum=FREQ;
00342       set_field_buffer(counter_field[ARRAYCALC],0,freqstring);
00343       sprintf(zerostring,"%u",Cop->counter_data[channel].zerocross);
00344       fieldnum=ZERO;
00345       set_field_buffer(counter_field[ARRAYCALC],0,zerostring);
00346     }
00347 
00348 }
00349 return 0;
00350 }
00351 
00352 
00353 /*Update the fields from the Cop data structure
00354 @param Cop the data structure to update the fields from
00355 */
00356 void UpdateFields(Cop_Data *Cop)
00357 {
00358 int channel;
00359 int fieldnum;
00360 char buffer[FIELDSEP+1];
00361 
00362 for(channel=0;channel<COUNTNUM;channel++)
00363   {
00364     fieldnum = RELOAD;
00365     sprintf(buffer,"%u",Cop->counter_config[channel].threshold);
00366     set_field_buffer(counter_field[ARRAYCALC],0,buffer);
00367     fieldnum = TRIG;
00368     set_field_buffer(counter_field[ARRAYCALC],0,trig_strings[Cop->counter_config[channel].trigger]);
00369     fieldnum = FLAG;
00370     set_field_buffer(counter_field[ARRAYCALC],0,flag_strings[Cop->counter_config[channel].flags]);
00371   }
00372 
00373 }
00374 
00375 /*Display current counter readings.
00376 The counters that are not "masked" are refreshed by reading from the 37e12 and updating the fields.
00377 @param fd the device to address
00378 @param form the form to update
00379 @param Cop the cop data structure storing counter information
00380 @param mask bitmask of the counters to refresh(in this program this is all but the currently selected field)
00381 */
00382 static int DisplayCounters(int fd, FORM *form, Cop_Data *Cop, unsigned char mask)
00383 {
00384 int channel;
00385 char buffer[1000];
00386 int fieldnum=0;
00387 char countstr[FIELDSEP+1];
00388 __u32 typemask=0;
00389 int rxnum=0;
00390 
00391 for(channel=0;channel<COUNTNUM;channel++)
00392 {
00393 
00394 if(mask&(1<<channel))
00395   {
00396     E12_CounterReadRQ(fd, channel);//request data
00397 
00398         while(!(typemask&(COUNTRESPONSE)))  //wait for data
00399         {//disregard any other data
00400           rxnum =read(fd,buffer,sizeof(buffer));//read data
00401           typemask = E12_Packet_Route(Cop,buffer, rxnum);//dig for AtoD data
00402 
00403           if(typemask&(NOTIFYRESPONSE))//zero cross notification received
00404               handlecrossing(Cop);
00405         }
00406 
00407     sprintf(countstr,"%u",Cop->counter_data[channel].counter);
00408 
00409     set_field_buffer(counter_field[ARRAYCALC],0,countstr);
00410     typemask=0;
00411   }
00412 }
00413 
00414 return 0;
00415 }
00416 
00417 /*Display counters not currently being modified
00418 This is a wrapper around Display counters that sets the mask.
00419 The mask is used to prevent counters currently being modified(the cursor is on that field) from changing dynamically.
00420 */
00421 static int DisplayUnusedCounters(int fd, FORM *form, Cop_Data *Cop)
00422 {
00423 FIELD *field =  current_field(form);
00424 int index =  field_index(field);
00425 int counter = index/FIELDNUM;
00426 int fieldnum = index%FIELDNUM;
00427 unsigned char mask = 0xff;
00428 
00429 if(fieldnum==COUNT)
00430 {
00431   mask&=~(1<<counter);
00432 //CURSEMESSAGE("counter %u masked\n",counter);
00433 }
00434 DisplayCounters(fd,counter_form,Cop,mask);
00435 return 0;
00436 }
00437 
00438 
00439 /*Insert a character into a field
00440 This calls form_driver to write to a field and updates the modified flag if the current field is valid
00441 */
00442 static int Insert_char(FORM *form,char ch)
00443 {
00444 FIELD *field =  current_field(form);
00445 int index =  field_index(field);
00446 int fieldnum = index%FIELDNUM;
00447 
00448 if(fieldnum<ZERO)//if this is a writable field, zero and freq are not
00449   {
00450    modified=1; //field has been modified
00451   form_driver(counter_form, ch);
00452   }
00453 return 0;
00454 }
00455 
00456 
00457 /*Display the form and counters, also handle any input from the keyboard
00458 */
00459 static int Form_Display(int fd)
00460 {
00461 int ch;
00462 
00463 Cop = CopDeviceCreate(0);
00464 
00465 UpdatetHardwareCounterInfo(fd, Cop);
00466 UpdateFields(Cop);
00467 
00468 while((ch = getch()) != KEY_F(1))
00469     {   
00470       DisplayUnusedCounters(fd,counter_form,Cop);
00471       switch(ch)
00472         {   case KEY_DOWN:
00473                 /* Go to next field */
00474                 form_driver(counter_form, REQ_DOWN_FIELD);
00475                 /* Go to the end of the present buffer */
00476                 /* Leaves nicely at the last character */
00477                 //form_driver(counter_form, REQ_END_LINE);
00478                 break;
00479             case KEY_UP:
00480                 /* Go to previous field */
00481                 form_driver(counter_form, REQ_UP_FIELD);
00482                 //form_driver(counter_form, REQ_END_LINE);
00483                 break;
00484             case KEY_LEFT:
00485                 /* Go to previous field */
00486                 form_driver(counter_form, REQ_LEFT_FIELD);
00487                 //form_driver(counter_form, REQ_END_LINE);
00488                 break;
00489             case KEY_RIGHT:
00490                 /* Go to previous field */
00491                 form_driver(counter_form, REQ_RIGHT_FIELD);
00492                 //form_driver(counter_form, REQ_END_LINE);
00493                 break;
00494             case KEY_BACKSPACE:
00495                 /* Go to previous field */
00496                 form_driver(counter_form, REQ_DEL_PREV);
00497             modified=1;//field has been modified
00498 //              form_driver(counter_form, REQ_PREV_CHAR);
00499                 break;
00500             case 10:
00501             /*enter was pressed, commit the current field's value*/
00502             modified=1; //treat field as modified
00503             //toggle position to turn on autocomplete
00504             form_driver(counter_form, REQ_RIGHT_FIELD);
00505             form_driver(counter_form, REQ_LEFT_FIELD);
00506                 break;
00507             case ERR:  //no key returned, just return to the top loop
00508           break;
00509             default:
00510                 /* If this is a normal character modify the current field */
00511             Insert_char(counter_form, ch);
00512                 break;
00513         }
00514     }
00515 
00516 CopDeviceDestroy(Cop);
00517 return 0;
00518 }
00519 
00523 int main(int argc, char **argv)
00524 {
00525 int fd;
00526 ARGCHECK(1);
00527 OPENDEV(fd,argv[1]);
00528 global_fd = fd;
00529 InitForm();
00530 Form_Display(fd);
00531 close(fd);
00532 destroyform();
00533 return 0;
00534 }

Generated on Thu Jan 8 09:51:00 2004 for PCM-37e12 by doxygen1.2.15