8 char* itoa(int val, int base){
10 static char buf[32] = {0};
14 for(; val && i ; --i, val /= base)
16 buf[i] = "0123456789abcdef"[val % base];
22 void initGpioSetup (gpioSetup* obj)
27 obj->shellCommand = new char[255];
35 obj->verbose = FASTGPIO_DEFAULT_VERBOSITY;
36 obj->debug = FASTGPIO_DEFAULT_DEBUG;
38 obj->cmdString = new char[255];
41 void usage(const char* progName) {
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);
55 void print(int verbosity, char* cmd, int pin, char* val)
57 if ( verbosity != FASTGPIO_VERBOSITY_QUIET &&
58 verbosity != FASTGPIO_VERBOSITY_JSON
61 printf(FASTGPIO_STDOUT_STRING, cmd, pin, val);
63 else if ( verbosity == FASTGPIO_VERBOSITY_JSON ) {
64 printf(FASTGPIO_JSON_STRING, cmd, pin, val);
68 int parseArguments(const char* progName, int argc, char* argv[], gpioSetup *setup)
70 // check for the correct number of arguments
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;
85 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_SET_DIR);
87 else if (strncmp(argv[0], "set-output", strlen("set-output") ) == 0 ) {
88 setup->cmd = GPIO_CMD_SET_DIRECTION;
90 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_SET_DIR);
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);
96 else if (strncmp(argv[0], "set", strlen("set") ) == 0 ) {
97 setup->cmd = GPIO_CMD_SET;
98 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_SET);
100 // get the write value
102 setup->pinValue = atoi(argv[2]);
109 else if (strncmp(argv[0], "read", strlen("read") ) == 0 ) {
110 setup->cmd = GPIO_CMD_READ;
111 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_READ);
113 else if (strncmp(argv[0], "mread", strlen("mread") ) == 0 ) {
115 setup->cmd = GPIO_CMD_READ_MASK;
116 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_READ);
117 setup->bitMask = strtol(argv[1], NULL, 16);
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);
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]);
144 else if (strncmp(argv[0], "pwm", strlen("pwm") ) == 0 ) {
145 setup->cmd = GPIO_CMD_PWM;
146 strcpy(setup->cmdString, FASTGPIO_CMD_STRING_PWM);
148 // get the freq and duty values
150 setup->pwmFreq = atoi(argv[2]);
151 setup->pwmDuty = atoi(argv[3]);
153 if ( argc == 5 ) setup->cycles = atoi(argv[4]); else setup->cycles = 0;
164 // get the pin number
165 setup->pinNumber = atoi(argv[1]);
170 // function to run gpio commands
171 int gpioRun(gpioSetup* setup)
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;
179 int status = EXIT_SUCCESS;
182 if (strcmp(DEVICE_TYPE, "ramips") == 0) {
183 gpioObj = new FastGpioOmega2();
185 gpioObj = new FastGpioOmega();
187 char* valString = new char[255];
188 // Modify here to point to Omega or Omega2 Object.
190 gpioObj->SetVerbosity(setup->verbose == FASTGPIO_VERBOSITY_ALL ? 1 : 0);
191 gpioObj->SetDebugMode(setup->debug);
194 switch (setup->cmd) {
196 gpioObj->SetDirection(setup->pinNumber, 1); // set to output
197 gpioObj->Set(setup->pinNumber, setup->pinValue);
199 strcpy(valString, (setup->pinValue == 1 ? "1" : "0") );
204 gpioObj->Read(setup->pinNumber, setup->pinValue);
205 strcpy(valString, (setup->pinValue == 1 ? "1" : "0") );
209 case GPIO_CMD_READ_MASK:
213 bitMask = setup->bitMask;
215 fullRegister = gpioObj->ReadFull(setup->pinNumber, setup->pinValue);
216 kbdRead = bitMask ^ (fullRegister & bitMask);
217 printf("0x%x\n", kbdRead);
221 case GPIO_CMD_READFULL:
223 usleep (10000); // magic workariund to prevent initial register misreading
225 bitMask = setup->bitMask;
231 fullRegister = gpioObj->ReadFull(setup->pinNumber, setup->pinValue);
233 kbdRead = bitMask ^ (fullRegister & bitMask);
237 if ( kbdRead != prevkbdRead) {
242 prevkbdRead = kbdRead;
244 if ( regCnt < 11 ) regCnt++;
246 if ( regCnt == 10 && prevRegCnt == 11 ){
248 // printf("%x\n", kbdRead);
249 sprintf(cmdShell, "%s %x\n", setup->shellCommand, kbdRead);
253 if ( kbdRead != 0 ) regCnt = 0; // remove it for holding the buttons
262 // gpioObj->Read(setup->pinNumber, setup->pinValue);
263 fullRegister = gpioObj->ReadFull(setup->pinNumber, setup->pinValue);
264 kbdRead = bitMask ^ (fullRegister & bitMask);
266 // printf("-> %u %u\n", prevRegister, fullRegister);
268 if ( prevkbdRead == kbdRead && kbdRead != 0 ){
270 prevkbdRead = kbdRead;
276 sprintf(cmdShell, "%s 0x%u\n", setup->shellCommand, kbdRead); // released, 0
280 prevkbdRead = kbdRead;
285 // if ( regOk != 0 ) {
286 sprintf(cmdShell, "%s 0x%x\n", setup->shellCommand, kbdRead);
299 case GPIO_CMD_SET_DIRECTION:
300 gpioObj->SetDirection(setup->pinNumber, setup->pinDir); // set pin direction
301 strcpy(valString, (setup->pinDir == 1 ? "output" : "input") );
304 case GPIO_CMD_GET_DIRECTION:
305 gpioObj->GetDirection(setup->pinNumber, setup->pinDir); // find pin direction
306 strcpy(valString, (setup->pinDir == 1 ? "output" : "input") );
308 case GPIO_CMD_PULSES:
309 pulseGpio(gpioObj,setup->pinNumber,setup->pathPulsesFile,setup->repeats);
311 gpioObj->SetDirection(38, 1); // set to output
313 for (a=0; a<100; a++) {
315 //// HIGH part of cycle
327 status = EXIT_FAILURE;
331 if (status != EXIT_FAILURE && valString[0] != 0 ) {
332 print(setup->verbose, setup->cmdString, setup->pinNumber, valString);
340 // function to run pwm commands
341 int pwmRun(gpioSetup* setup)
342 { //Gotta change this to either reference the Omega or Omega 2 object
344 char* valString = new char[255];
346 // check for correct command
347 if (setup->cmd != GPIO_CMD_PWM) {
352 pwmObj.SetVerbosity(setup->verbose == FASTGPIO_VERBOSITY_ALL ? 1 : 0);
353 pwmObj.SetDebugMode(setup->debug);
357 pwmObj.Pwm(setup->pinNumber, setup->pwmFreq, setup->pwmDuty, setup->cycles );
364 // function to note the PID of the child process
365 int noteChildPid(int pinNum, int pid)
368 std::ofstream myfile;
370 // determine thef file name and open the file
371 snprintf(pathname, sizeof(pathname), PID_FILE, pinNum);
372 myfile.open (pathname);
374 // write the pid to the file
384 // function to read any existing pid notes and kill the child processes
385 int killOldProcess(int pinNum)
392 std::ifstream myfile;
394 // determine thef file name and open the file
395 snprintf(pathname, sizeof(pathname), PID_FILE, pinNum);
396 myfile.open (pathname);
399 if ( myfile.is_open() ) {
400 // file exists, check for pid
401 myfile.getline(line, 255);
407 sprintf(cmd, "kill %d >& /dev/null", pid);
409 if (FASTGPIO_VERBOSE > 0) printf("Exiting current pwm process (pid: %d)\n", pid);
417 // function to kill any old processes, based on which command is being run
418 int checkOldProcess(gpioSetup *setup)
420 switch (setup->cmd) {
422 case GPIO_CMD_SET_DIRECTION:
424 // kill the old process
425 killOldProcess(setup->pinNumber);
437 void pulse(FastGpio *gpioObj,int pinNum,int highMicros, int lowMicros)
439 gpioObj->Set(pinNum,1);
441 gpioObj->Set(pinNum,0);
446 int pulseGpio(FastGpio *gpioObj,int pinNum, char* pathToFile, int repeats)
448 gpioObj->SetDirection(pinNum,1);
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;
458 // Load data from the file
463 while ((fscanf(pFile, "%d,%d\n", pUpTimes,pDownTimes) != EOF) && (i++ < 200))
472 printf("Error opening the file\n");
477 while (repeats-- > 0)
480 pDownTimes = downTimes;
481 while (*pUpTimes != 0)
483 // printf("Pulsing Up Time: %d, Down Time: %d\n",*pUpTimes,*pDownTimes);
484 pulse(gpioObj,pinNum,*pUpTimes,*pDownTimes);
497 int main(int argc, char* argv[])
502 const char *progname;
503 char* val = new char[255];
505 gpioSetup* setup = new gpioSetup;
507 // reset gpio setup and set defaults
508 initGpioSetup(setup);
510 setup->verbose = FASTGPIO_DEFAULT_VERBOSITY;
511 setup->debug = FASTGPIO_DEFAULT_DEBUG;
513 // save the program name
517 //// parse the option arguments
518 while ((ch = getopt(argc, argv, "vqud")) != -1) {
522 setup->verbose = FASTGPIO_VERBOSITY_ALL;
526 setup->verbose = FASTGPIO_VERBOSITY_QUIET;
530 setup->verbose = FASTGPIO_VERBOSITY_JSON;
542 // advance past the option arguments
546 // parse the arguments
547 if (parseArguments(progname, argc, argv, setup) == EXIT_FAILURE) {
551 // check for any pwm processes already running on this pin
552 status = checkOldProcess(setup);
555 if (setup->cmd != GPIO_CMD_PWM){
556 // single gpio command
557 status = gpioRun(setup);
560 //// continuous gpio commands, need another process
562 // create the new process
566 // child process, run the pwm
567 status = pwmRun(setup);
571 if (FASTGPIO_VERBOSE > 0) printf("Launched child pwm process, pid: %d \n", pid);
572 noteChildPid(setup->pinNumber, pid);
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);