initial commit
[ETG_Helmet] / SOFTWARE / UTILS / fast-gpio / src / main.cpp
1 // #include <stdio.h>
2 // #include <stdlib.h>
3 // #include <string.h>
4 #include <time.h>
5
6 #include <main.h>
7
8 char* itoa(int val, int base){
9         
10         static char buf[32] = {0};
11         
12         int i = 30;
13         
14         for(; val && i ; --i, val /= base)
15         
16                 buf[i] = "0123456789abcdef"[val % base];
17         
18         return &buf[i+1];
19         
20 }
21
22 void initGpioSetup (gpioSetup* obj)
23 {
24         obj->pinNumber  = -1;
25         obj->pinValue   = 0;
26         obj->pinDir     = 0;
27         obj->shellCommand = new char[255];
28         obj->bitMask    = 0;
29         
30         obj->bPwm       = 0;
31         obj->pwmFreq    = 0;
32         obj->pwmDuty    = 0;
33         obj->cycles     = 0;
34
35         obj->verbose    = FASTGPIO_DEFAULT_VERBOSITY;
36         obj->debug      = FASTGPIO_DEFAULT_DEBUG;
37
38         obj->cmdString  = new char[255];
39 }
40
41 void usage(const char* progName) {
42         printf("Usage:\n");
43         printf("\t%s set-input <gpio>\n", progName);
44         printf("\t%s set-output <gpio>\n", progName);
45         printf("\t%s get-direction <gpio>\n", progName);
46         printf("\t%s read <gpio>\n", progName);
47         printf("\t%s mread <hex bitmask>\n", progName);
48         printf("\t%s bgread <hex bitmask> <command to execute>\n", progName);
49         printf("\t%s set <gpio> <value: 0 or 1>\n", progName);
50         printf("\t%s pwm <gpio> <freq in Hz/10> <duty cycle percentage> [<cycles>]\n", progName);
51         printf("\t%s pulses <gpio> <path_pulses_file> <repeats>\n",progName);
52         printf("\n");
53 }
54
55 void print(int verbosity, char* cmd, int pin, char* val)
56 {
57         if      (       verbosity != FASTGPIO_VERBOSITY_QUIET &&
58                         verbosity != FASTGPIO_VERBOSITY_JSON
59                 ) 
60         {
61                 printf(FASTGPIO_STDOUT_STRING, cmd, pin, val);
62         }
63         else if ( verbosity == FASTGPIO_VERBOSITY_JSON ) {
64                 printf(FASTGPIO_JSON_STRING, cmd, pin, val);
65         }
66 }
67
68 int parseArguments(const char* progName, int argc, char* argv[], gpioSetup *setup)
69 {
70         // check for the correct number of arguments
71         if ( argc < 2 ) 
72         {
73                 usage(progName);
74                 return EXIT_FAILURE;
75         }
76
77
78         // parse the command line arguments
79         //      arg1 - command: read, set
80         //      arg2 - gpio pin number
81         //      arg3 - value to write in case of set
82         if (strncmp(argv[0], "set-input", strlen("set-input") ) == 0 )  {
83                 setup->cmd              = GPIO_CMD_SET_DIRECTION;
84                 setup->pinDir   = 0;
85                 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_SET_DIR);
86         }
87         else if (strncmp(argv[0], "set-output", strlen("set-output") ) == 0 )   {
88                 setup->cmd              = GPIO_CMD_SET_DIRECTION;
89                 setup->pinDir   = 1;
90                 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_SET_DIR);
91         }
92         else if (strncmp(argv[0], "get-direction", strlen("get-direction") ) == 0 )     {
93                 setup->cmd              = GPIO_CMD_GET_DIRECTION;
94                 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_GET_DIR);
95         }
96         else if (strncmp(argv[0], "set", strlen("set") ) == 0 ) {
97                 setup->cmd              = GPIO_CMD_SET;
98                 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_SET);
99
100                 // get the write value
101                 if ( argc == 3 ) {
102                         setup->pinValue = atoi(argv[2]);
103                 }
104                 else {
105                         usage(argv[0]);
106                         return EXIT_FAILURE;
107                 }
108         }
109         else if (strncmp(argv[0], "read", strlen("read") ) == 0 )       {
110                 setup->cmd              = GPIO_CMD_READ;
111                 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_READ);
112         }
113         else if (strncmp(argv[0], "mread", strlen("mread") ) == 0 )     {
114                 if ( argc > 1 ) {
115                         setup->cmd = GPIO_CMD_READ_MASK;
116                         strcpy(setup->cmdString, FASTGPIO_CMD_STRING_READ);
117                         setup->bitMask = strtol(argv[1], NULL, 16);
118                 } else {
119                         usage(argv[0]);
120                         return EXIT_FAILURE;
121                 }
122         }
123         else if (strncmp(argv[0], "bgread", strlen("bgread") ) == 0 )   {
124                 if ( strcmp(argv[1], "") != 0 && argc > 2 ) {
125                         setup->cmd              = GPIO_CMD_READFULL;
126                         strcpy(setup->cmdString, FASTGPIO_CMD_STRING_READ);
127                         setup->shellCommand = argv[2];
128 //                      setup->bitMask = atoi(argv[1]);
129                         setup->bitMask = strtol(argv[1], NULL, 16);
130 //                      printf("--> %s, %lu, %lu\n", argv[1], atoi(argv[1]), setup->bitMask);
131                 } else {
132                         usage(argv[0]);
133                         return EXIT_FAILURE;
134                 }
135         }
136         else if (strncmp(argv[0], "pulses", strlen("pulses") ) == 0 )   {
137                 setup->cmd              = GPIO_CMD_PULSES;
138                 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_PULSES);
139                 // get the path to the pulses file and repeat number
140                 setup->pathPulsesFile = argv[2];
141                 setup->repeats = atoi(argv[3]);
142         }
143
144         else if (strncmp(argv[0], "pwm", strlen("pwm") ) == 0 ) {
145                 setup->cmd      = GPIO_CMD_PWM;
146                 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_PWM);
147
148                 // get the freq and duty values
149                 if ( argc >= 4 ) {
150                         setup->pwmFreq  = atoi(argv[2]);
151                         setup->pwmDuty  = atoi(argv[3]);
152
153                         if ( argc == 5 ) setup->cycles  = atoi(argv[4]); else setup->cycles = 0;
154                 }
155                 else {
156                         usage(argv[0]);
157                         return EXIT_FAILURE;
158                 }
159         }
160         else {
161                 return EXIT_FAILURE;
162         }
163
164         // get the pin number
165         setup->pinNumber        = atoi(argv[1]);
166
167         return EXIT_SUCCESS;
168 }
169
170 // function to run gpio commands
171 int gpioRun(gpioSetup* setup)
172 {
173         char                    cmdShell[255];
174 //      volatile unsigned long int      fullRegister=0, prevRegister=0, regOk=0, prevRegOk=0, bitMask=0, kbdRead=0;
175         volatile unsigned long int      fullRegister=0, regCnt = 0, prevRegCnt = 0, kbdRead = 0, prevkbdRead = 0, bitMask = 0;
176         unsigned int            a, counter=0;
177         char                    justPress = false;
178
179         int status      = EXIT_SUCCESS;
180         FastGpio        * gpioObj;
181                 // object setup
182         if (strcmp(DEVICE_TYPE, "ramips") == 0) {
183                 gpioObj = new FastGpioOmega2();
184         } else {
185                 gpioObj = new FastGpioOmega();
186         }
187         char*           valString = new char[255];
188         // Modify here to point to Omega or Omega2 Object. 
189         // object setup
190         gpioObj->SetVerbosity(setup->verbose == FASTGPIO_VERBOSITY_ALL ? 1 : 0);
191         gpioObj->SetDebugMode(setup->debug);
192
193         // object operations    
194         switch (setup->cmd) {
195                 case GPIO_CMD_SET:
196                         gpioObj->SetDirection(setup->pinNumber, 1); // set to output
197                         gpioObj->Set(setup->pinNumber, setup->pinValue);
198
199                         strcpy(valString, (setup->pinValue == 1 ? "1" : "0") );
200                         break;
201
202                 case GPIO_CMD_READ:
203
204                         gpioObj->Read(setup->pinNumber, setup->pinValue);
205                         strcpy(valString, (setup->pinValue == 1 ? "1" : "0") );
206
207                         break;
208
209                 case GPIO_CMD_READ_MASK:
210
211                         valString[0] = 0;
212
213                         bitMask = setup->bitMask;
214
215                         fullRegister = gpioObj->ReadFull(setup->pinNumber, setup->pinValue);
216                         kbdRead = bitMask ^ (fullRegister & bitMask);
217                         printf("0x%x\n", kbdRead);
218
219                         break;
220
221                 case GPIO_CMD_READFULL:
222
223                         usleep (10000); // magic workariund to prevent initial register misreading 
224
225                         bitMask = setup->bitMask;
226
227                         while (1){
228
229
230 /*
231                                 fullRegister = gpioObj->ReadFull(setup->pinNumber, setup->pinValue);
232
233                                 kbdRead = bitMask ^ (fullRegister & bitMask);
234
235                                 // single click 
236
237                                 if ( kbdRead != prevkbdRead) {
238                                         prevRegCnt = regCnt;
239                                         regCnt = 0;
240                                 }
241
242                                 prevkbdRead = kbdRead;
243
244                                 if ( regCnt < 11 ) regCnt++;
245
246                                 if ( regCnt == 10 && prevRegCnt == 11 ){
247
248 //                                      printf("%x\n", kbdRead);
249                                         sprintf(cmdShell, "%s %x\n", setup->shellCommand, kbdRead);
250                                         system( cmdShell );
251
252                                         usleep(100000);
253                                         if ( kbdRead != 0 ) regCnt = 0; // remove it for holding the buttons
254                                 }
255                         
256                                 usleep (10000);
257 */
258
259
260                                 while (1) {
261
262         //                              gpioObj->Read(setup->pinNumber, setup->pinValue);
263                                         fullRegister = gpioObj->ReadFull(setup->pinNumber, setup->pinValue);
264                                         kbdRead = bitMask ^ (fullRegister & bitMask);
265
266         //                              printf("-> %u %u\n", prevRegister, fullRegister);
267
268                                         if ( prevkbdRead == kbdRead && kbdRead != 0 ){ 
269 //                                              regOk = kbdRead;
270                                                 prevkbdRead = kbdRead;
271                                                 break;
272                                         } 
273
274                                         if ( justPress ){
275                                                 justPress = false;
276                                                 sprintf(cmdShell, "%s 0x%u\n", setup->shellCommand, kbdRead); // released, 0
277                                                 system( cmdShell );
278                                         }
279
280                                         prevkbdRead = kbdRead;
281
282                                         usleep(10000);
283                                 }
284
285 //                              if ( regOk != 0 ) {
286                                         sprintf(cmdShell, "%s 0x%x\n", setup->shellCommand, kbdRead);
287                                         system( cmdShell );
288                                         usleep(100000);
289                                         justPress = true;
290 //                              }
291 //                              regOk = 0;
292
293
294
295                         }
296
297                         break;
298
299                 case GPIO_CMD_SET_DIRECTION:
300                         gpioObj->SetDirection(setup->pinNumber, setup->pinDir); // set pin direction
301                         strcpy(valString, (setup->pinDir == 1 ? "output" : "input") );
302                         break;
303
304                 case GPIO_CMD_GET_DIRECTION:
305                         gpioObj->GetDirection(setup->pinNumber, setup->pinDir); // find pin direction
306                         strcpy(valString, (setup->pinDir == 1 ? "output" : "input") );
307                         break;
308                 case GPIO_CMD_PULSES:
309                         pulseGpio(gpioObj,setup->pinNumber,setup->pathPulsesFile,setup->repeats);
310 /*
311                                 gpioObj->SetDirection(38, 1); // set to output
312
313                                 for (a=0; a<100; a++) {
314
315                                         //// HIGH part of cycle
316                                         gpioObj->Set(38, 1);
317                                         usleep(500);
318
319                                         // LOW part of cycle
320                                         gpioObj->Set(38, 0);
321                                         usleep(500);
322                                 }
323 */
324                         break;
325
326                 default:
327                         status = EXIT_FAILURE;
328                         break;
329         }
330
331         if (status != EXIT_FAILURE && valString[0] != 0 ) {
332                 print(setup->verbose, setup->cmdString, setup->pinNumber, valString);
333         }
334
335         // clean-up
336         delete valString;
337         return status;
338 }
339
340 // function to run pwm commands
341 int pwmRun(gpioSetup* setup)
342 {       //Gotta change this to either reference the Omega or Omega 2 object
343         FastPwm         pwmObj;
344         char*           valString = new char[255];
345
346         // check for correct command
347         if (setup->cmd != GPIO_CMD_PWM) {
348                 return EXIT_FAILURE;
349         }
350
351         // object setup
352         pwmObj.SetVerbosity(setup->verbose == FASTGPIO_VERBOSITY_ALL ? 1 : 0);
353         pwmObj.SetDebugMode(setup->debug);
354
355
356         // object operations    
357         pwmObj.Pwm(setup->pinNumber, setup->pwmFreq, setup->pwmDuty, setup->cycles );
358
359         // clean-up
360         delete valString;
361         return EXIT_SUCCESS;
362 }
363
364 // function to note the PID of the child process
365 int noteChildPid(int pinNum, int pid)
366 {
367         char    pathname[255];
368         std::ofstream myfile;
369         
370         // determine thef file name and open the file
371         snprintf(pathname, sizeof(pathname), PID_FILE, pinNum);
372         myfile.open (pathname);
373
374         // write the pid to the file
375         myfile << pid;
376         myfile << "\n";
377
378         myfile.close();
379
380
381         return EXIT_SUCCESS;
382
383
384 // function to read any existing pid notes and kill the child processes
385 int killOldProcess(int pinNum)
386 {
387         char    pathname[255];
388         char    line[255];
389         char    cmd[255];
390
391         int     pid;
392         std::ifstream myfile;
393
394         // determine thef file name and open the file
395         snprintf(pathname, sizeof(pathname), PID_FILE, pinNum);
396         myfile.open (pathname);
397
398         // read the file
399         if ( myfile.is_open() ) {
400                 // file exists, check for pid
401                 myfile.getline(line, 255);
402                 pid = atoi(line);
403
404                 // kill the process
405                 if (pid > 0)
406                 {
407                         sprintf(cmd, "kill %d >& /dev/null", pid);
408                         system(cmd);
409                         if (FASTGPIO_VERBOSE > 0) printf("Exiting current pwm process (pid: %d)\n", pid);
410                 }
411         }
412
413
414         return EXIT_SUCCESS;
415 }
416
417 // function to kill any old processes, based on which command is being run
418 int checkOldProcess(gpioSetup *setup)
419 {
420         switch (setup->cmd) {
421                 case GPIO_CMD_SET:
422                 case GPIO_CMD_SET_DIRECTION:
423                 case GPIO_CMD_PWM:
424                         // kill the old process
425                         killOldProcess(setup->pinNumber);
426                         break;
427
428                 default:
429                         // do nothing
430                         break;
431         }
432
433         return EXIT_SUCCESS;
434 }
435
436
437 void pulse(FastGpio *gpioObj,int pinNum,int highMicros, int lowMicros)
438 {
439         gpioObj->Set(pinNum,1);
440         usleep(highMicros);
441         gpioObj->Set(pinNum,0);
442         usleep(lowMicros);
443 }
444
445
446 int pulseGpio(FastGpio *gpioObj,int pinNum, char* pathToFile, int repeats)
447 {
448         gpioObj->SetDirection(pinNum,1);
449
450         FILE * pFile;
451         pFile = fopen (pathToFile,"r");
452         // Max code size is 200 
453         int* upTimes = new int[200];
454         int* downTimes = new int[200];
455         int* pUpTimes = upTimes;
456         int* pDownTimes = downTimes;
457
458         // Load data from the file
459         if (pFile != NULL)
460         {
461                 int i = 0;
462
463                 while ((fscanf(pFile, "%d,%d\n", pUpTimes,pDownTimes) != EOF) && (i++ < 200))
464                 {
465                         pUpTimes++;
466                         pDownTimes++;
467                 }
468                 fclose (pFile);
469         }
470         else
471         {
472                 printf("Error opening the file\n");
473                 return 1;
474         }
475
476         // Play the code 
477         while (repeats-- > 0)
478         {
479                 pUpTimes = upTimes;
480                 pDownTimes = downTimes;
481                 while (*pUpTimes != 0)
482                 {
483                         // printf("Pulsing Up Time: %d, Down Time: %d\n",*pUpTimes,*pDownTimes);
484                         pulse(gpioObj,pinNum,*pUpTimes,*pDownTimes);
485
486                         pUpTimes++;
487                         pDownTimes++;
488                 }
489         }
490
491         delete[] upTimes;
492         delete[] downTimes;
493
494
495 }
496
497 int main(int argc, char* argv[])
498 {
499         int             status;
500         int             ch;
501
502         const char      *progname;
503         char*           val     = new char[255];
504         
505         gpioSetup*      setup   = new gpioSetup;
506
507         // reset gpio setup and set defaults
508         initGpioSetup(setup);
509
510         setup->verbose          = FASTGPIO_DEFAULT_VERBOSITY;
511         setup->debug            = FASTGPIO_DEFAULT_DEBUG;
512
513         // save the program name
514         progname = argv[0];
515
516
517         //// parse the option arguments
518         while ((ch = getopt(argc, argv, "vqud")) != -1) {
519                 switch (ch) {
520                 case 'v':
521                         // verbose output
522                         setup->verbose = FASTGPIO_VERBOSITY_ALL;
523                         break;
524                 case 'q':
525                         // quiet output
526                         setup->verbose = FASTGPIO_VERBOSITY_QUIET;
527                         break;
528                 case 'u':
529                         // ubus output
530                         setup->verbose = FASTGPIO_VERBOSITY_JSON;
531                         break;
532                 case 'd':
533                         // debug mode
534                         setup->debug    = 1;
535                         break;
536                 default:
537                         usage(progname);
538                         return 0;
539                 }
540         }
541
542         // advance past the option arguments
543         argc    -= optind;
544         argv    += optind;
545
546         // parse the arguments
547         if (parseArguments(progname, argc, argv, setup) == EXIT_FAILURE) {
548                 return EXIT_FAILURE;
549         }
550
551         // check for any pwm processes already running on this pin
552         status = checkOldProcess(setup);
553
554         // run the command
555         if (setup->cmd != GPIO_CMD_PWM){
556                 // single gpio command
557                 status = gpioRun(setup);
558         }
559         else {
560                 //// continuous gpio commands, need another process
561
562                 // create the new process
563                 pid_t pid = fork();
564
565                 if (pid == 0) {
566                         // child process, run the pwm
567                         status = pwmRun(setup);
568                 }
569                 else {
570                         // parent process
571                         if (FASTGPIO_VERBOSE > 0) printf("Launched child pwm process, pid: %d \n", pid);
572                         noteChildPid(setup->pinNumber, pid);
573
574                         if ( setup->verbose == FASTGPIO_VERBOSITY_JSON ) {
575                                 sprintf(val, "%dHz with %d%% duty", setup->pwmFreq, setup->pwmDuty);
576                                 printf(FASTGPIO_JSON_STRING, setup->cmdString, setup->pinNumber, val);
577                         }
578                 }
579         }
580
581
582         // clean-up
583         delete  val;
584         delete  setup;
585
586         return 0;
587 }
Contact me: dev (at) shalnoff (dot) com
PGP fingerprint: A6B8 3B23 6013 F18A 0C71 198B 83D8 C64D 917A 5717