mirror of https://github.com/joan2937/pigpio
This commit is contained in:
commit
56b5f62885
|
@ -0,0 +1,63 @@
|
|||
CC = gcc
|
||||
AR = ar
|
||||
RANLIB = ranlib
|
||||
SIZE = size
|
||||
|
||||
CFLAGS = -O3 -Wall
|
||||
|
||||
all: libpigpio.a checklib demolib pig2vcd pigpiod pigs
|
||||
|
||||
checklib: checklib.o libpigpio.a
|
||||
$(CC) -o checklib checklib.c -L. -lpigpio -lpthread -lrt
|
||||
|
||||
demolib: demolib.o libpigpio.a
|
||||
$(CC) -o demolib demolib.c -L. -lpigpio -lpthread -lrt
|
||||
|
||||
pig2vcd: pig2vcd.o
|
||||
$(CC) -o pig2vcd pig2vcd.c
|
||||
|
||||
pigpiod: pigpiod.o libpigpio.a
|
||||
$(CC) -o pigpiod pigpiod.c -L. -lpigpio -lpthread -lrt
|
||||
|
||||
pigs: pigs.o command.o
|
||||
$(CC) -o pigs pigs.c command.c
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
clean:
|
||||
rm -f *.o *.i *.s *~ libpigpio.a checklib demolib pigpiod pigs pig2vcd
|
||||
|
||||
install: $(LIB)
|
||||
sudo install -m 0755 -d /usr/local/bin
|
||||
sudo install -m 0755 -d /usr/local/include
|
||||
sudo install -m 0755 -d /usr/local/lib
|
||||
sudo install -m 0755 pig2vcd /usr/local/bin
|
||||
sudo install -m 0755 pigpiod /usr/local/bin
|
||||
sudo install -m 0755 pigs /usr/local/bin
|
||||
sudo install -m 0644 pigpio.h /usr/local/include
|
||||
sudo install -m 0644 libpigpio.a /usr/local/lib
|
||||
|
||||
uninstall:
|
||||
sudo rm -f /usr/local/bin/pig2vcd
|
||||
sudo rm -f /usr/local/bin/pigpiod
|
||||
sudo rm -f /usr/local/bin/pigs
|
||||
sudo rm -f /usr/local/include/pigpio.h
|
||||
sudo rm -f /usr/local/lib/libpigpio.a
|
||||
|
||||
LIB = libpigpio.a
|
||||
OBJ = pigpio.o command.o
|
||||
|
||||
$(LIB): $(OBJ)
|
||||
$(AR) rcs $(LIB) $(OBJ)
|
||||
$(RANLIB) $(LIB)
|
||||
$(SIZE) $(LIB)
|
||||
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
checklib.o: checklib.c pigpio.h
|
||||
demolib.o: demolib.c pigpio.h
|
||||
pig2vcd: pigpio.h
|
||||
pigpiod: pigpiod.c pigpio.h
|
||||
pigs: pigs.c command.c pigpio.h command.h
|
|
@ -0,0 +1,67 @@
|
|||
INSTALL
|
||||
|
||||
Extract the archive to a directory.
|
||||
|
||||
IN THAT DIRECTORY
|
||||
|
||||
Enter the following two commands (in this order)
|
||||
|
||||
make
|
||||
make install
|
||||
|
||||
This will install:
|
||||
the library (libpigpio.a) in /usr/local/lib
|
||||
the header file (pigpio.h) in /usr/local/include
|
||||
the daemon (pigpiod) in /usr/local/bin
|
||||
the socket interface (pigs) in /usr/local/bin
|
||||
the utility pig2vcd in /usr/local/bin
|
||||
|
||||
TEST
|
||||
|
||||
To test the library do
|
||||
|
||||
sudo ./checklib
|
||||
|
||||
checklib.c, demolib.c, pig2vcd.c, pigpiod.c, and pigs.c show examples
|
||||
of interfacing with the library.
|
||||
|
||||
DAEMON
|
||||
|
||||
To launch the daemon do
|
||||
|
||||
sudo pigpiod (pigpiod -? for options)
|
||||
|
||||
Once the daemon is launched the socket and fifo interfaces will be
|
||||
available.
|
||||
|
||||
When the library starts it locks
|
||||
|
||||
/var/run/pigpio.pid
|
||||
|
||||
The file should be deleted when the library terminates.
|
||||
|
||||
SOCKET INTERFACE
|
||||
|
||||
Use pigs for the socket interface (pigs help for help).
|
||||
|
||||
FIFO INTERFACE
|
||||
|
||||
The fifo interface accepts commands written to /dev/pigpio.
|
||||
|
||||
Results are read from /dev/pigout.
|
||||
|
||||
Errors are output on /dev/pigerr.
|
||||
|
||||
To test the fifo interface perhaps do
|
||||
|
||||
cat /dev/pigout &
|
||||
cat /dev/pigerr &
|
||||
|
||||
echo "help" >/dev/pigpio
|
||||
|
||||
STOP DAEMON
|
||||
|
||||
To stop the daemon
|
||||
|
||||
sudo killall pigpiod
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
|
|
@ -0,0 +1,709 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/*
|
||||
This version is for pigpio version 3+
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
|
||||
#define GREENLED 16
|
||||
#define SDDET 47
|
||||
#define SDCLK 48
|
||||
|
||||
int test =1;
|
||||
int passes=0;
|
||||
int expect=0;
|
||||
|
||||
struct timeval libInitTime;
|
||||
|
||||
int GPIO=4;
|
||||
|
||||
unsigned inited, count, onMicros, offMicros;
|
||||
|
||||
void tick(void)
|
||||
{
|
||||
/* count ticks
|
||||
*/
|
||||
|
||||
static struct timeval lastTime;
|
||||
struct tm tmp;
|
||||
struct timeval nowTime;
|
||||
char buf[32];
|
||||
|
||||
gettimeofday(&nowTime, NULL);
|
||||
|
||||
localtime_r(&nowTime.tv_sec, &tmp);
|
||||
strftime(buf, sizeof(buf), "%F@%T", &tmp);
|
||||
|
||||
printf("%s.%03d\n", buf, (int)nowTime.tv_usec/1000);
|
||||
|
||||
/*timersub(&nowTime, &lastTime, &diffTime);*/
|
||||
|
||||
lastTime = nowTime;
|
||||
|
||||
if (inited)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 1;
|
||||
|
||||
gettimeofday(&lastTime, NULL);
|
||||
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void tickEx(void * userdata)
|
||||
{
|
||||
}
|
||||
|
||||
void alert(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
/* accumulate number of level changes and average time gpio
|
||||
was on and off. Hopefully the ratio should reflect the
|
||||
selected pulsewidth.
|
||||
*/
|
||||
|
||||
static uint32_t lastTick;
|
||||
|
||||
uint32_t diffTick;
|
||||
|
||||
if (inited)
|
||||
{
|
||||
count++;
|
||||
|
||||
diffTick = tick - lastTick;
|
||||
|
||||
if (level == 0)
|
||||
{
|
||||
/* elapsed time was on */
|
||||
onMicros = onMicros + diffTick;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* elapsed time was off */
|
||||
offMicros = offMicros + diffTick;
|
||||
}
|
||||
lastTick = tick;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 1;
|
||||
lastTick = tick;
|
||||
onMicros = 0;
|
||||
offMicros = 0;
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void alertEx(int gpio, int level, uint32_t tick, void * userdata)
|
||||
{
|
||||
}
|
||||
|
||||
static void timerTest(unsigned waitfor, unsigned ms)
|
||||
{
|
||||
unsigned ep, ep1, ep2;
|
||||
|
||||
ep= (waitfor*1000)/ms; ep1=ep-1; ep2=ep+1;
|
||||
|
||||
printf("Timer ticktest (%d ms), wait %d seconds\n", ms, waitfor);
|
||||
printf("Expect %d to %d ticks\n", ep1, ep2);
|
||||
|
||||
inited = 0;
|
||||
gpioSetTimerFunc(0, ms, tick);
|
||||
sleep(waitfor);
|
||||
gpioSetTimerFunc(0, ms, NULL);
|
||||
|
||||
/* and the stats were? */
|
||||
|
||||
printf("ticks=%d\n", count);
|
||||
|
||||
if ((count>=ep1) && (count<=ep2))
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("TEST %d: FAILED\n\n", test);
|
||||
}
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
static void servoTest(unsigned waitfor, unsigned pulsewidth)
|
||||
{
|
||||
int ticks, on, off;
|
||||
unsigned expectedPulses, ep1, ep2;
|
||||
float expectedRatio, er1, er2;
|
||||
float ratio;
|
||||
|
||||
expectedPulses=(500*waitfor)/10; ep1=(490*waitfor)/10; ep2=(510*waitfor)/10;
|
||||
expectedRatio = (float)(20000-pulsewidth)/(float)pulsewidth;
|
||||
er1=expectedRatio*0.9; er2=expectedRatio*1.1;
|
||||
|
||||
printf("Servo pulse test (%d micros), wait %d seconds\n",
|
||||
pulsewidth, waitfor);
|
||||
printf("Expect %d pulses and an off/on ratio of %.1f\n",
|
||||
expectedPulses, expectedRatio);
|
||||
|
||||
gpioServo(GPIO, pulsewidth);
|
||||
|
||||
inited = 0;
|
||||
gpioSetAlertFunc(GPIO, alert);
|
||||
sleep(waitfor);
|
||||
gpioSetAlertFunc(GPIO, NULL);
|
||||
|
||||
gpioServo(GPIO, 0);
|
||||
|
||||
/* and the stats were? */
|
||||
|
||||
ticks = count/2; on = onMicros/1000; off = offMicros/1000;
|
||||
ratio = (float)off/(float)on;
|
||||
|
||||
printf("servo pulses=%d on ms=%d off ms=%d ratio=%.1f\n", ticks, on, off, ratio);
|
||||
|
||||
if ( ((ticks>ep1) && (ticks<ep2)) && ((ratio>er1) && (ratio<er2)) )
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("TEST %d: FAILED\n\n", test);
|
||||
}
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
static void pwmTest(unsigned waitfor, unsigned pulsewidth)
|
||||
{
|
||||
int on, off;
|
||||
float expectedRatio, er1, er2;
|
||||
float ratio;
|
||||
|
||||
expectedRatio = (float)(255-pulsewidth)/255.0;
|
||||
er1=expectedRatio*0.9; er2=expectedRatio*1.1;
|
||||
|
||||
printf("PWM test (%d), wait %d seconds\n", pulsewidth, waitfor);
|
||||
printf("Expect an off/on ratio of %.3f\n", expectedRatio);
|
||||
|
||||
inited = 0;
|
||||
gpioSetAlertFunc(GPIO, alert);
|
||||
gpioPWM(GPIO, pulsewidth);
|
||||
sleep(waitfor);
|
||||
gpioPWM(GPIO, 0);
|
||||
gpioSetAlertFunc(GPIO, NULL);
|
||||
|
||||
/* and the stats were? */
|
||||
|
||||
on = onMicros/1000; off = offMicros/1000;
|
||||
ratio = (float)off/((float)on+(float)off);
|
||||
|
||||
printf("pwm on ms=%d off ms=%d ratio=%.3f\n", on, off, ratio);
|
||||
|
||||
if ((ratio>er1) && (ratio<er2))
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("TEST %d: FAILED\n\n", test);
|
||||
}
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
void expectExpected(int expected)
|
||||
{
|
||||
if (expect==expected)
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else printf("TEST %d: FAILED\n\n", test);
|
||||
|
||||
expect = 0;
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
void checkValidation(void)
|
||||
{
|
||||
int secs, micros;
|
||||
|
||||
/* check function parameter validation */
|
||||
|
||||
printf("Function parameter validation tests\n");
|
||||
|
||||
printf("Expect ERROR messages\n\n");
|
||||
|
||||
if (gpioSetMode(PI_MAX_GPIO+1, 0) == PI_BAD_GPIO) expect++;
|
||||
if (gpioSetMode(PI_MIN_GPIO-1, 0) == PI_BAD_GPIO) expect++;
|
||||
if (gpioSetMode(PI_MIN_GPIO, PI_ALT3+1) == PI_BAD_MODE) expect++;
|
||||
if (gpioSetMode(PI_MAX_GPIO, PI_INPUT-1) == PI_BAD_MODE) expect++;
|
||||
|
||||
expectExpected(4);
|
||||
|
||||
if (gpioGetMode(PI_MAX_GPIO+1) == PI_BAD_GPIO) expect++;
|
||||
if (gpioGetMode(PI_MIN_GPIO-1) == PI_BAD_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioSetPullUpDown(PI_MAX_GPIO+1, 0) == PI_BAD_GPIO) expect++;
|
||||
if (gpioSetPullUpDown(PI_MIN_GPIO-1, 0) == PI_BAD_GPIO) expect++;
|
||||
if (gpioSetPullUpDown(PI_MIN_GPIO, PI_PUD_UP+1) == PI_BAD_PUD) expect++;
|
||||
if (gpioSetPullUpDown(PI_MAX_GPIO, PI_PUD_OFF-1) == PI_BAD_PUD) expect++;
|
||||
|
||||
expectExpected(4);
|
||||
|
||||
if (gpioRead(PI_MIN_GPIO-1) == PI_BAD_GPIO) expect++;
|
||||
if (gpioRead(PI_MAX_GPIO+1) == PI_BAD_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioWrite(PI_MAX_GPIO+1, 0) == PI_BAD_GPIO) expect++;
|
||||
if (gpioWrite(PI_MIN_GPIO-1, 0) == PI_BAD_GPIO) expect++;
|
||||
if (gpioWrite(PI_MIN_GPIO, PI_ON+1) == PI_BAD_LEVEL) expect++;
|
||||
if (gpioWrite(PI_MAX_GPIO, PI_OFF-1) == PI_BAD_LEVEL) expect++;
|
||||
|
||||
expectExpected(4);
|
||||
|
||||
if (gpioPWM(PI_MAX_USER_GPIO+1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioPWM(PI_MIN_GPIO-1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioPWM(PI_MIN_GPIO, PI_DEFAULT_DUTYCYCLE_RANGE+1) ==
|
||||
PI_BAD_DUTYCYCLE) expect++;
|
||||
if (gpioPWM(PI_MAX_USER_GPIO, -1) == PI_BAD_DUTYCYCLE) expect++;
|
||||
|
||||
expectExpected(4);
|
||||
|
||||
if (gpioSetPWMrange(PI_MAX_USER_GPIO+1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioSetPWMrange(PI_MIN_GPIO-1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioSetPWMrange(GPIO, 24) == PI_BAD_DUTY_RANGE) expect++;
|
||||
if (gpioSetPWMrange(GPIO, 40001) == PI_BAD_DUTY_RANGE) expect++;
|
||||
|
||||
expectExpected(4);
|
||||
|
||||
if (gpioGetPWMrange(PI_MAX_USER_GPIO+1) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioGetPWMrange(PI_MIN_GPIO-1) == PI_BAD_USER_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioGetPWMrealRange(PI_MAX_USER_GPIO+1) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioGetPWMrealRange(PI_MIN_GPIO-1) == PI_BAD_USER_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioSetPWMfrequency(PI_MAX_USER_GPIO+1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioSetPWMfrequency(PI_MIN_GPIO-1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioGetPWMfrequency(PI_MAX_USER_GPIO+1) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioGetPWMfrequency(PI_MIN_GPIO-1) == PI_BAD_USER_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioServo(PI_MAX_USER_GPIO+1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioServo(PI_MIN_GPIO-1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioServo(GPIO, 1) == PI_BAD_PULSEWIDTH) expect++;
|
||||
if (gpioServo(GPIO,-1) == PI_BAD_PULSEWIDTH) expect++;
|
||||
if (gpioServo(GPIO, 499) == PI_BAD_PULSEWIDTH) expect++;
|
||||
if (gpioServo(GPIO, 2501) == PI_BAD_PULSEWIDTH) expect++;
|
||||
|
||||
expectExpected(6);
|
||||
|
||||
if (gpioSetAlertFunc(PI_MAX_USER_GPIO+1, alert) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioSetAlertFunc(PI_MIN_GPIO-1, alert) == PI_BAD_USER_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioSetAlertFuncEx(PI_MAX_USER_GPIO+1, alertEx, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioSetAlertFuncEx(PI_MIN_GPIO-1, alertEx, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioSetWatchdog(PI_MAX_USER_GPIO+1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioSetWatchdog(PI_MIN_GPIO-1, 0) == PI_BAD_USER_GPIO) expect++;
|
||||
if (gpioSetWatchdog(GPIO, 60001) == PI_BAD_WDOG_TIMEOUT) expect++;
|
||||
if (gpioSetWatchdog(GPIO, -1) == PI_BAD_WDOG_TIMEOUT) expect++;
|
||||
if (gpioSetWatchdog(GPIO, 0) == 0) expect++;
|
||||
|
||||
expectExpected(5);
|
||||
|
||||
if (gpioSetTimerFunc(10, 20, tick) == PI_BAD_TIMER) expect++;
|
||||
if (gpioSetTimerFunc(-1, 20, tick) == PI_BAD_TIMER) expect++;
|
||||
if (gpioSetTimerFunc(0, 9, tick) == PI_BAD_MS) expect++;
|
||||
if (gpioSetTimerFunc(0, 60001, tick) == PI_BAD_MS) expect++;
|
||||
|
||||
expectExpected(4);
|
||||
|
||||
if (gpioSetTimerFuncEx(10, 20, tickEx, 0) == PI_BAD_TIMER) expect++;
|
||||
if (gpioSetTimerFuncEx(-1, 20, tickEx, 0) == PI_BAD_TIMER) expect++;
|
||||
if (gpioSetTimerFuncEx(0, 9, tickEx, 0) == PI_BAD_MS) expect++;
|
||||
if (gpioSetTimerFuncEx(0, 60001, tickEx, 0) == PI_BAD_MS) expect++;
|
||||
|
||||
expectExpected(4);
|
||||
|
||||
if (gpioTime(-1, &secs, µs) == PI_BAD_TIMETYPE) expect++;
|
||||
if (gpioTime(2, &secs, µs) == PI_BAD_TIMETYPE) expect++;
|
||||
|
||||
expectExpected(2);
|
||||
|
||||
if (gpioSleep(-1, 1, 0) == PI_BAD_TIMETYPE) expect++;
|
||||
if (gpioSleep(2, 1, 0) == PI_BAD_TIMETYPE) expect++;
|
||||
if (gpioSleep(PI_TIME_ABSOLUTE, -1, 0) == PI_BAD_SECONDS) expect++;
|
||||
if (gpioSleep(PI_TIME_ABSOLUTE, 0, -1) == PI_BAD_MICROS) expect++;
|
||||
if (gpioSleep(PI_TIME_ABSOLUTE, 0, 1000000) == PI_BAD_MICROS) expect++;
|
||||
if (gpioSleep(PI_TIME_RELATIVE, -1, 0) == PI_BAD_SECONDS) expect++;
|
||||
if (gpioSleep(PI_TIME_RELATIVE, 0, -1) == PI_BAD_MICROS) expect++;
|
||||
if (gpioSleep(PI_TIME_RELATIVE, 0, 1000000) == PI_BAD_MICROS) expect++;
|
||||
|
||||
expectExpected(8);
|
||||
}
|
||||
|
||||
void checkGpioTime(void)
|
||||
{
|
||||
struct timeval nowA, nowR, tvR, tvA, diffR, diffA;
|
||||
int diffMicrosA, diffMicrosR;
|
||||
int i, ok;
|
||||
|
||||
int secR, micR, secA, micA;
|
||||
|
||||
printf("Library timer tests.\n");
|
||||
|
||||
ok = 0;
|
||||
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
gettimeofday(&nowA, NULL); /* reference absolute time */
|
||||
|
||||
gpioTime(PI_TIME_ABSOLUTE, &secA, &micA); /* absolute library time */
|
||||
gpioTime(PI_TIME_RELATIVE, &secR, &micR); /* relative library time */
|
||||
|
||||
timersub(&nowA, &libInitTime, &nowR); /* reference relative time */
|
||||
|
||||
tvA.tv_sec = secA; tvA.tv_usec = micA;
|
||||
tvR.tv_sec = secR; tvR.tv_usec = micR;
|
||||
|
||||
/* difference between reference and library absolute time */
|
||||
timersub(&tvA, &nowA, &diffA);
|
||||
|
||||
/* difference between reference and library relative time */
|
||||
timersub(&tvR, &nowR, &diffR);
|
||||
|
||||
|
||||
diffMicrosA = (diffA.tv_sec*1000000)+diffA.tv_usec;
|
||||
|
||||
diffMicrosR = (diffR.tv_sec*1000000)+diffR.tv_usec;
|
||||
|
||||
if (diffMicrosA < 0) diffMicrosA = -diffMicrosA;
|
||||
if (diffMicrosR < 0) diffMicrosR = -diffMicrosR;
|
||||
|
||||
if ((diffMicrosA < 10) && (diffMicrosR < 500)) ok++;
|
||||
|
||||
printf("ABS time diff=%d, REL time diff=%d\n",
|
||||
diffMicrosA, diffMicrosR);
|
||||
}
|
||||
|
||||
if (ok == 10)
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else printf("TEST %d: FAILED\n\n", test);
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
void checkGpioSleep(unsigned timetype)
|
||||
{
|
||||
struct timeval t1, t2, tD;
|
||||
int i, ok, secs, micros, diffMicros, expMicros, errMicros;
|
||||
|
||||
if (timetype == PI_TIME_ABSOLUTE)
|
||||
printf("Library gpioSleep ABSOLUTE tests.\n");
|
||||
else
|
||||
printf("Library gpioSleep RELATIVE tests.\n");
|
||||
|
||||
ok = 0;
|
||||
|
||||
for (i=15; i>0; i--)
|
||||
{
|
||||
expMicros = i * 100000;
|
||||
|
||||
if (timetype == PI_TIME_ABSOLUTE)
|
||||
{
|
||||
gpioTime(PI_TIME_ABSOLUTE, &secs, µs);
|
||||
|
||||
secs += (i / 10);
|
||||
micros += (i % 10) * 100000;
|
||||
|
||||
if (micros > 999999) { secs++; micros -= 1000000; }
|
||||
}
|
||||
else
|
||||
{
|
||||
secs = (i / 10);
|
||||
micros = (i % 10) * 100000;
|
||||
}
|
||||
|
||||
gettimeofday(&t1, NULL);
|
||||
|
||||
gpioSleep(timetype, secs, micros);
|
||||
|
||||
gettimeofday(&t2, NULL);
|
||||
|
||||
timersub(&t2, &t1, &tD);
|
||||
|
||||
diffMicros = (tD.tv_sec*1000000)+tD.tv_usec;
|
||||
|
||||
errMicros = diffMicros - expMicros;
|
||||
|
||||
if (errMicros < 500) ok++;
|
||||
|
||||
printf("secs=%d micros=%d err=%d\n", secs, micros, errMicros);
|
||||
}
|
||||
|
||||
if (ok == 15)
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else printf("TEST %d: FAILED\n\n", test);
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
int countBank2PinChanges(int pin, int loops)
|
||||
{
|
||||
static uint32_t old=0;
|
||||
|
||||
uint32_t new, changes;
|
||||
int i, count;
|
||||
|
||||
count = 0;
|
||||
|
||||
for (i=0;i<loops;i++)
|
||||
{
|
||||
new = gpioRead_Bits_32_53();
|
||||
|
||||
changes = new ^ old;
|
||||
|
||||
if (changes & (1<<(pin-32))) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void checkReadWriteBits(void)
|
||||
{
|
||||
uint32_t bank1, bank2;
|
||||
|
||||
int i, ok, count1, count2;
|
||||
|
||||
printf("Library gpioRead/Write_Bits_x_x_Set/Clear Tests\n");
|
||||
printf("Expect 0 for pin 47 and >200000 for pin 48.\n");
|
||||
printf("Expect the green LED to flash.\n\n");
|
||||
|
||||
ok = 0;
|
||||
|
||||
for (i=0; i<20; i++)
|
||||
{
|
||||
gpioWrite_Bits_0_31_Set(1<<GREENLED);
|
||||
|
||||
count1 = countBank2PinChanges(SDDET, 1000000);
|
||||
|
||||
gpioWrite_Bits_0_31_Clear(1<<GREENLED);
|
||||
|
||||
count2 = countBank2PinChanges(SDCLK, 1000000);
|
||||
|
||||
bank1 = gpioRead_Bits_0_31();
|
||||
bank2 = gpioRead_Bits_32_53();
|
||||
|
||||
printf("bank1=%08X, bank2=%08X, 47=%d 48=%d\n",
|
||||
bank1, bank2, count1, count2);
|
||||
|
||||
if ((count1 == 0) && (count2 > 200000)) ok++;
|
||||
}
|
||||
|
||||
if (ok == 20)
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else printf("TEST %d: FAILED\n\n", test);
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
void checkGpioTick(void)
|
||||
{
|
||||
uint32_t startTick, endTick;
|
||||
int diffTick;
|
||||
|
||||
printf("Library gpioTick Test\n");
|
||||
printf("Expect approximately 2 million ticks to have elapsed.\n\n");
|
||||
|
||||
startTick = gpioTick();
|
||||
sleep(2); /* 2 seconds being 2 million ticks */
|
||||
endTick = gpioTick();
|
||||
|
||||
diffTick = endTick - startTick;
|
||||
|
||||
printf("%d ticks have elapsed\n", diffTick);
|
||||
|
||||
if ((diffTick >= 1990000) && (diffTick <= 2010000))
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
else printf("TEST %d: FAILED\n\n", test);
|
||||
|
||||
++test;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
int waitfor;
|
||||
|
||||
int version, micros=5, millis=100;
|
||||
|
||||
if (argc > 1) GPIO = atoi(argv[1]);
|
||||
|
||||
fprintf(stderr,
|
||||
"*****************************************************************\n"\
|
||||
"* WARNING: This program sends pulses to gpio #%02d *\n"\
|
||||
"* Make sure that nothing which could be damaged is *\n"\
|
||||
"* connected to this gpio. A LED or similar should be OK *\n"\
|
||||
"* although nothing needs to be connected. *\n"\
|
||||
"* *\n"\
|
||||
"* NOTE: many of the tests are statistical in nature, assuming *\n"\
|
||||
"* that events of a short nature will on average be detected *\n"\
|
||||
"* by sampling. Don't fret if a particular test fails, try *\n"\
|
||||
"* running the tests again. *\n"\
|
||||
"* *\n"\
|
||||
"* You may choose another gpio by specifying its number on *\n"\
|
||||
"* the command line, e.g. sudo ./checklib 17 will use gpio 17. *\n"\
|
||||
"* *\n"\
|
||||
"* Press y (RETURN) to continue, any other character to cancel. *\n"\
|
||||
"*****************************************************************\n", GPIO);
|
||||
|
||||
if (getchar() != 'y') return 0;
|
||||
|
||||
printf("Initialisation test\n");
|
||||
|
||||
if (argc > 2) micros = atoi(argv[2]);
|
||||
|
||||
if (argc > 3) millis = atoi(argv[3]);
|
||||
|
||||
gpioCfgBufferSize(millis);
|
||||
|
||||
gpioCfgClock(micros, PI_CLOCK_PCM, PI_CLOCK_PLLD);
|
||||
|
||||
gettimeofday(&libInitTime, NULL);
|
||||
|
||||
version = gpioInitialise();
|
||||
|
||||
if (version<0)
|
||||
{
|
||||
printf("TEST %d: FAILED\nFATAL ERROR\n", test);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("TEST %d: PASS, pigpio version is %d\n\n", test, version);
|
||||
++passes;
|
||||
}
|
||||
|
||||
++test;
|
||||
|
||||
waitfor = 2;
|
||||
|
||||
printf("Alert function test, wait %d seconds\n", waitfor);
|
||||
printf("No detected events on gpio 4 expected\n");
|
||||
|
||||
inited = 0;
|
||||
gpioSetAlertFunc(GPIO, alert);
|
||||
sleep(waitfor);
|
||||
gpioSetAlertFunc(GPIO, NULL);
|
||||
|
||||
printf("Events=%d\n", count);
|
||||
|
||||
if (count) printf("TEST %d: FAILED\n\n", test);
|
||||
else
|
||||
{
|
||||
printf("TEST %d: PASS\n\n", test);
|
||||
++passes;
|
||||
}
|
||||
|
||||
++test;
|
||||
|
||||
servoTest(10, 500);
|
||||
servoTest(10, 1500);
|
||||
servoTest(10, 2500);
|
||||
|
||||
pwmTest(5, 50);
|
||||
pwmTest(5, 100);
|
||||
pwmTest(5, 150);
|
||||
pwmTest(5, 200);
|
||||
|
||||
timerTest(5, 100);
|
||||
timerTest(5, 250);
|
||||
timerTest(5, 333);
|
||||
timerTest(5, 1000);
|
||||
|
||||
checkValidation();
|
||||
|
||||
checkGpioTime();
|
||||
|
||||
checkGpioSleep(PI_TIME_RELATIVE);
|
||||
|
||||
checkGpioSleep(PI_TIME_ABSOLUTE);
|
||||
|
||||
checkReadWriteBits();
|
||||
|
||||
checkGpioTick();
|
||||
|
||||
printf("Hardware revision is %d\n\n", gpioHardwareRevision());
|
||||
|
||||
printf("Summary: %d tests, %d passes\n", test-1, passes);
|
||||
|
||||
gpioTerminate(); /* stop DMA and free memory */
|
||||
|
||||
return (passes - (test-1));
|
||||
}
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/*
|
||||
This version is for pigpio version 4+
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
#include "command.h"
|
||||
|
||||
cmdInfo_t cmdInfo[]=
|
||||
{
|
||||
{PI_CMD_BR1, "BR1", 1, 3},
|
||||
{PI_CMD_BR2, "BR2", 1, 3},
|
||||
{PI_CMD_BC1, "BC1", 7, 1},
|
||||
{PI_CMD_BC2, "BC2", 7, 1},
|
||||
{PI_CMD_BS1, "BS1", 7, 1},
|
||||
{PI_CMD_BS2, "BS2", 7, 1},
|
||||
{PI_CMD_HWVER, "HWVER", 1, 4},
|
||||
{PI_CMD_MODES, "MODES", 8, 0},
|
||||
{PI_CMD_MODES, "M", 8, 0},
|
||||
{PI_CMD_MODEG, "MODEG", 2, 2},
|
||||
{PI_CMD_MODEG, "MG" , 2, 2},
|
||||
{PI_CMD_NO, "NO", 1, 2},
|
||||
{PI_CMD_NB, "NB", 4, 0},
|
||||
{PI_CMD_NP, "NP", 2, 0},
|
||||
{PI_CMD_NC, "NC", 2, 0},
|
||||
{PI_CMD_PWM, "PWM", 3, 0},
|
||||
{PI_CMD_PWM, "P", 3, 0},
|
||||
{PI_CMD_PFS, "PFS", 3, 2},
|
||||
{PI_CMD_PFG, "PFG", 2, 2},
|
||||
{PI_CMD_PRS, "PRS", 3, 2},
|
||||
{PI_CMD_PRG, "PRG", 2, 2},
|
||||
{PI_CMD_PRRG, "PRRG", 2, 2},
|
||||
{PI_CMD_PUD, "PUD", 9, 0},
|
||||
{PI_CMD_READ, "READ", 2, 2},
|
||||
{PI_CMD_READ, "R", 2, 2},
|
||||
{PI_CMD_SERVO, "SERVO", 3, 0},
|
||||
{PI_CMD_SERVO, "S", 3, 0},
|
||||
{PI_CMD_WRITE, "WRITE", 3, 0},
|
||||
{PI_CMD_WRITE, "W", 3, 0},
|
||||
{PI_CMD_WDOG, "WDOG", 3, 0},
|
||||
{PI_CMD_TICK, "TICK", 1, 4},
|
||||
{PI_CMD_TICK, "T", 1, 4},
|
||||
{PI_CMD_HELP, "HELP", 6, 5},
|
||||
{PI_CMD_HELP, "H", 6, 5},
|
||||
};
|
||||
|
||||
char * cmdUsage = "\
|
||||
BR1 read gpios bank 1\n\
|
||||
BR2 read gpios bank 2\n\
|
||||
BC1 x clear gpios in bank 1\n\
|
||||
BC2 x clear gpios in bank 2\n\
|
||||
BS1 x set gpios in bank 1\n\
|
||||
BS2 x set gpios in bank 2\n\
|
||||
HWVER return hardware version\n\
|
||||
MODES/M g m set gpio mode\n\
|
||||
MODEG/MG g get gpio mode\n\
|
||||
NO request notification handle\n\
|
||||
NB h x start notification\n\
|
||||
NP h pause notification\n\
|
||||
NC h close notification\n\
|
||||
PWM/P u d set PWM value for gpio\n\
|
||||
PFS u d set PWM frequency for gpio\n\
|
||||
PFG u get PWM frequency for gpio\n\
|
||||
PRS u d set PWM range for gpio\n\
|
||||
PRG u get PWM range for gpio\n\
|
||||
PRRG u get PWM real range for gpio\n\
|
||||
PUD g p set gpio pull up/down\n\
|
||||
READ/R g read gpio\n\
|
||||
SERVO/S u d set servo value for gpio\n\
|
||||
WRITE/W g d write value to gpio\n\
|
||||
WDOG u d set watchdog on gpio\n\
|
||||
TICK/T return current tick\n\
|
||||
HELP/H displays command help\n\
|
||||
\n\
|
||||
d = decimal value\n\
|
||||
g = gpio (0-53)\n\
|
||||
h = handle (0-31)\n\
|
||||
m = mode (RW540123)\n\
|
||||
p = pud (ODU)\n\
|
||||
u = user gpio (0-31)\n\
|
||||
x = hex value\n\
|
||||
";
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int error;
|
||||
char * str;
|
||||
} errInfo_t;
|
||||
|
||||
static errInfo_t errInfo[]=
|
||||
{
|
||||
{PI_INIT_FAILED , "pigpio initialisation failed"},
|
||||
{PI_BAD_USER_GPIO , "gpio not 0-31"},
|
||||
{PI_BAD_GPIO , "gpio not 0-53"},
|
||||
{PI_BAD_MODE , "mode not 0-7"},
|
||||
{PI_BAD_LEVEL , "level not 0-1"},
|
||||
{PI_BAD_PUD , "pud not 0-2"},
|
||||
{PI_BAD_PULSEWIDTH , "pulsewidth not 0 or 500-2500"},
|
||||
{PI_BAD_DUTYCYCLE , "dutycycle not 0-255"},
|
||||
{PI_BAD_TIMER , "timer not 0-9"},
|
||||
{PI_BAD_MS , "ms not 10-60000"},
|
||||
{PI_BAD_TIMETYPE , "timetype not 0-1"},
|
||||
{PI_BAD_SECONDS , "seconds < 0"},
|
||||
{PI_BAD_MICROS , "micros not 0-999999"},
|
||||
{PI_TIMER_FAILED , "gpioSetTimerFunc failed"},
|
||||
{PI_BAD_WDOG_TIMEOUT , "timeout not 0-60000"},
|
||||
{PI_NO_ALERT_FUNC , "DEPRECATED"},
|
||||
{PI_BAD_CLK_PERIPH , "clock peripheral not 0-1"},
|
||||
{PI_BAD_CLK_SOURCE , "clock source not 0-1"},
|
||||
{PI_BAD_CLK_MICROS , "clock micros not 1, 2, 4, 5, 8, or 10"},
|
||||
{PI_BAD_BUF_MILLIS , "buf millis not 100-10000"},
|
||||
{PI_BAD_DUTY_RANGE , "dutycycle range not 25-40000"},
|
||||
{PI_BAD_SIGNUM , "signum not 0-63"},
|
||||
{PI_BAD_PATHNAME , "can't open pathname"},
|
||||
{PI_NO_HANDLE , "no handle available"},
|
||||
{PI_BAD_HANDLE , "unknown notify handle"},
|
||||
{PI_BAD_IF_FLAGS , "ifFlags > 3"},
|
||||
{PI_BAD_CHANNEL , "DMA channel not 0-14"},
|
||||
{PI_BAD_SOCKET_PORT , "socket port not 1024-30000"},
|
||||
{PI_BAD_FIFO_COMMAND , "unknown fifo command"},
|
||||
{PI_BAD_SECO_CHANNEL , "DMA secondary channel not 0-6"},
|
||||
{PI_NOT_INITIALISED , "function called before gpioInitialise"},
|
||||
{PI_INITIALISED , "function called after gpioInitialise"},
|
||||
{PI_BAD_WAVE_MODE , "waveform mode not 0-1"},
|
||||
{PI_BAD_CFG_INTERNAL , "bad parameter in gpioCfgInternals call"},
|
||||
{PI_BAD_WAVE_BAUD , "baud rate not 100-250000"},
|
||||
{PI_TOO_MANY_PULSES , "waveform has too many pulses"},
|
||||
{PI_TOO_MANY_CHARS , "waveform has too many chars"},
|
||||
{PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"},
|
||||
|
||||
};
|
||||
|
||||
static char * fmtMdeStr="RW540123";
|
||||
static char * fmtPudStr="ODU";
|
||||
|
||||
static int cmdMatch(char * str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<(sizeof(cmdInfo)/sizeof(cmdInfo_t)); i++)
|
||||
{
|
||||
if (strcasecmp(str, cmdInfo[i].name) == 0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cmdParse(char * buf, cmdCmd_t * cmd)
|
||||
{
|
||||
char str[8];
|
||||
int f, valid, idx, val;
|
||||
char * ptr;
|
||||
char c, t;
|
||||
|
||||
sscanf(buf, " %7s", str);
|
||||
|
||||
cmd->cmd = -1;
|
||||
|
||||
idx = cmdMatch(str);
|
||||
|
||||
if (idx < 0) return idx;
|
||||
|
||||
valid = 0;
|
||||
|
||||
cmd->cmd = cmdInfo[idx].cmd;
|
||||
cmd->p1 = 0;
|
||||
cmd->p2 = 0;
|
||||
|
||||
switch (cmdInfo[idx].vt)
|
||||
{
|
||||
case 1: /* BR1 BR2 HWVER NO TICK */
|
||||
f = sscanf(buf, " %7s %c", str, &t);
|
||||
if (f == 1) valid = 1;
|
||||
break;
|
||||
|
||||
case 2: /* MODEG READ NC NP PFG PRG PRRG */
|
||||
f = sscanf(buf, " %7s %d %c", str, &cmd->p1, &t);
|
||||
if (f == 2) valid = 1;
|
||||
break;
|
||||
|
||||
case 3: /* WRITE PWM PRS PFS SERVO WDOG */
|
||||
f = sscanf(buf, " %7s %d %d %c", str, &cmd->p1, &cmd->p2, &t);
|
||||
if (f == 3) valid = 1;
|
||||
break;
|
||||
|
||||
case 4: /* NB */
|
||||
f = sscanf(buf, " %7s %d %x %c", str, &cmd->p1, &cmd->p2, &t);
|
||||
if (f == 3) valid = 1;
|
||||
break;
|
||||
|
||||
case 6: /* HELP */
|
||||
valid = 1;
|
||||
break;
|
||||
|
||||
case 7: /* BC1 BC2 BS1 BS2 */
|
||||
f = sscanf(buf, " %7s %x %c", str, &cmd->p1, &t);
|
||||
if (f == 2) valid = 1;
|
||||
break;
|
||||
|
||||
case 8: /* MODES */
|
||||
f = sscanf(buf, " %7s %d %c %c", str, &cmd->p1, &c, &t);
|
||||
if (f == 3)
|
||||
{
|
||||
val = toupper(c);
|
||||
ptr = strchr(fmtMdeStr, val);
|
||||
if (ptr != NULL)
|
||||
{
|
||||
val = ptr - fmtMdeStr;
|
||||
cmd->p2 = val;
|
||||
valid = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 9: /* PUD */
|
||||
f = sscanf(buf, " %7s %d %c %c", str, &cmd->p1, &c, &t);
|
||||
if (f == 3)
|
||||
{
|
||||
val = toupper(c);
|
||||
ptr = strchr(fmtPudStr, val);
|
||||
if (ptr != NULL)
|
||||
{
|
||||
val = ptr - fmtPudStr;
|
||||
cmd->p2 = val;
|
||||
valid = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (valid) return idx;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
void cmdFatal(char *fmt, ...)
|
||||
{
|
||||
char buf[128];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char * cmdErrStr(int error)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<(sizeof(errInfo)/sizeof(errInfo_t)); i++)
|
||||
{
|
||||
if (errInfo[i].error == error) return errInfo[i].str;
|
||||
}
|
||||
return "unknown error";
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/*
|
||||
This version is for pigpio version 3+
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int cmd;
|
||||
char * name;
|
||||
int vt;
|
||||
int rv;
|
||||
} cmdInfo_t;
|
||||
|
||||
extern cmdInfo_t cmdInfo[];
|
||||
|
||||
extern char * cmdUsage;
|
||||
|
||||
int cmdParse(char * buf, cmdCmd_t * cmd);
|
||||
|
||||
char * cmdErrStr(int error);
|
||||
|
||||
void cmdFatal(char *fmt, ...);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,673 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/*
|
||||
This version is for pigpio version 3+
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
|
||||
/* ===========================================================================
|
||||
THIS PROGRAM NEEDS THE I2C DEVICE AND DEVELOPMENT LIBRARY
|
||||
|
||||
TO GET THE NEEDED FILES DO
|
||||
|
||||
sudo apt-get install libi2c-dev
|
||||
|
||||
BEFORE RUNNING THE PROGRAM ENSURE THAT THE I2C DEVICE IS PRESENT
|
||||
|
||||
sudo modprobe i2c-bcm2708
|
||||
sudo modprobe i2c-dev
|
||||
sudo chmod o+rw /dev/i2c*
|
||||
=========================================================================== */
|
||||
|
||||
/*
|
||||
|
||||
P1 Name gpio used for
|
||||
|
||||
3 SDA 0/2 i2c
|
||||
5 SCL 1/3 i2c
|
||||
7 --- 4 LASER
|
||||
8 TXD 14 LED1
|
||||
10 RXD 15 LED2
|
||||
11 --- 17 SERVO 1
|
||||
12 --- 18 SERVO 2
|
||||
13 --- 21/27 SERVO 3
|
||||
15 --- 22 LED3
|
||||
16 --- 23 TI Launchpad
|
||||
18 --- 24 Sonar trigger
|
||||
19 MOSI 10 Sonar echo
|
||||
21 MISO 9 Motor B In 1
|
||||
22 --- 25 LDR
|
||||
23 SCLK 11 Motor B In 2
|
||||
24 CE0 8 Motor A In1
|
||||
26 CE1 7 Motor A In2
|
||||
|
||||
*/
|
||||
|
||||
#define LASER 4
|
||||
#define MOTOR_A_IN2 7
|
||||
#define MOTOR_A_IN1 8
|
||||
#define MOTOR_B_IN1 9
|
||||
#define SONAR_ECHO 10
|
||||
#define MOTOR_B_IN2 11
|
||||
#define LED1 14
|
||||
#define LED2 15
|
||||
#define SERVO1 17
|
||||
#define SERVO2 18
|
||||
#define SERVO3 21
|
||||
#define LED3 22
|
||||
#define LAUNCHPAD 23
|
||||
#define SONAR_TRIGGER 24
|
||||
#define LDR 25
|
||||
|
||||
#define LEDS 4
|
||||
|
||||
short rawAcc[3];
|
||||
short rawGyr[3];
|
||||
short rawMag[3];
|
||||
|
||||
#define ROLL 0
|
||||
#define PITCH 1
|
||||
#define YAW 2
|
||||
|
||||
#define ACC_ORIENTATION(X, Y, Z) \
|
||||
{rawAcc[ROLL] = -X; rawAcc[PITCH] = -Y; rawAcc[YAW] = Z;}
|
||||
|
||||
#define GYRO_ORIENTATION(X, Y, Z) \
|
||||
{rawGyr[ROLL] = Y; rawGyr[PITCH] = -X; rawGyr[YAW] = -Z;}
|
||||
|
||||
#define MAG_ORIENTATION(X, Y, Z) \
|
||||
{rawMag[ROLL] = X; rawMag[PITCH] = Y; rawMag[YAW] = -Z;}
|
||||
|
||||
|
||||
#define CALIBRATIONS 200
|
||||
|
||||
#define ADXL345_I2C_ADDR 0x53
|
||||
#define ITG3200_I2C_ADDR 0x68
|
||||
|
||||
static int version, micros=5, millis=100;
|
||||
|
||||
static volatile unsigned long launchpadPulses;
|
||||
static volatile unsigned long launchpad5;
|
||||
static volatile unsigned long launchpad10;
|
||||
static volatile unsigned long launchpad15;
|
||||
static volatile unsigned long launchpadOutRange;
|
||||
static volatile int launchpadErr;
|
||||
static volatile uint32_t LDRrechargeTick;
|
||||
|
||||
|
||||
/* forward prototypes */
|
||||
|
||||
void LEDlaserTick (void);
|
||||
void motorTick(void);
|
||||
void i2cTick (void);
|
||||
void servoTick (void);
|
||||
void sonarLDRtick(void);
|
||||
|
||||
void launchpadAlert(int gpio, int level, uint32_t tick);
|
||||
void sonarAlert(int gpio, int level, uint32_t tick);
|
||||
void LDRalert(int gpio, int level, uint32_t tick);
|
||||
|
||||
void putTTY(char * buf);
|
||||
void putTTYstr(int row, int col, char * buf);
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char str[256];
|
||||
|
||||
if (argc > 1) micros = atoi(argv[1]);
|
||||
|
||||
if (argc > 2) millis = atoi(argv[2]);
|
||||
|
||||
putTTY("\033c"); /* clear console */
|
||||
|
||||
gpioCfgBufferSize(millis);
|
||||
|
||||
gpioCfgClock(micros, PI_CLOCK_PCM, PI_CLOCK_PLLD);
|
||||
|
||||
|
||||
/* before using the library you must call gpioInitialise */
|
||||
|
||||
version = gpioInitialise();
|
||||
|
||||
if (version >= 0)
|
||||
{
|
||||
/* initialise pins, only gpio numbers are supported */
|
||||
|
||||
gpioSetMode(SERVO1, PI_OUTPUT);
|
||||
gpioSetMode(SERVO2, PI_OUTPUT);
|
||||
gpioSetMode(SERVO3, PI_OUTPUT);
|
||||
gpioSetMode(LASER, PI_OUTPUT);
|
||||
gpioSetMode(LED1, PI_OUTPUT);
|
||||
gpioSetMode(LED2, PI_OUTPUT);
|
||||
gpioSetMode(LED3, PI_OUTPUT);
|
||||
gpioSetMode(MOTOR_A_IN1, PI_OUTPUT);
|
||||
gpioSetMode(MOTOR_A_IN2, PI_OUTPUT);
|
||||
gpioSetMode(MOTOR_B_IN1, PI_OUTPUT);
|
||||
gpioSetMode(MOTOR_B_IN2, PI_OUTPUT);
|
||||
|
||||
gpioSetMode(SONAR_TRIGGER, PI_OUTPUT);
|
||||
gpioWrite (SONAR_TRIGGER, PI_OFF);
|
||||
|
||||
gpioSetMode(SONAR_ECHO, PI_INPUT);
|
||||
gpioSetMode(LAUNCHPAD, PI_INPUT);
|
||||
gpioSetMode(LDR, PI_INPUT);
|
||||
|
||||
/* update i2c fifty times a second, timer #0 */
|
||||
|
||||
gpioSetTimerFunc(0, 20, i2cTick);
|
||||
|
||||
//gpioSetTimerFunc(0, 1000, servoTick);
|
||||
|
||||
/* update LEDs and laser once a second, timer #1 */
|
||||
|
||||
gpioSetTimerFunc(1, 1000, LEDlaserTick);
|
||||
|
||||
/* update motors every three seconds, timer #2 */
|
||||
|
||||
gpioSetTimerFunc(2, 3000, motorTick);
|
||||
|
||||
/* update sonar/LDR 10 times a second, timer #3 */
|
||||
|
||||
gpioSetTimerFunc(3, 100, sonarLDRtick);
|
||||
|
||||
/* an attachecd TI launchpad is transmitting high pulses of
|
||||
15, 35, 55, 75, ..., 975, 995 microseconds repeating with 50
|
||||
microseconds off between each pulse */
|
||||
|
||||
gpioSetAlertFunc(LAUNCHPAD, launchpadAlert);
|
||||
|
||||
/* monitor sonar echos */
|
||||
|
||||
gpioSetAlertFunc(SONAR_ECHO, sonarAlert);
|
||||
|
||||
/* monitor LDR level changes */
|
||||
|
||||
gpioSetAlertFunc(LDR, LDRalert);
|
||||
|
||||
while (1)
|
||||
{
|
||||
sleep(1);
|
||||
|
||||
sprintf(str, "TI pulses %8ld", launchpadPulses);
|
||||
putTTYstr(9, 1, str);
|
||||
|
||||
sprintf(str, "+/-5 %8ld", launchpad5);
|
||||
putTTYstr(10, 6, str);
|
||||
|
||||
sprintf(str, "+/-10 %8ld", launchpad10);
|
||||
putTTYstr(11, 5, str);
|
||||
|
||||
sprintf(str, "+/-15 %8ld", launchpad15);
|
||||
putTTYstr(12, 5, str);
|
||||
|
||||
sprintf(str, "Others %8ld (last %d) ",
|
||||
launchpadOutRange, launchpadErr);
|
||||
putTTYstr(13, 4, str);
|
||||
}
|
||||
}
|
||||
|
||||
gpioTerminate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LEDlaserTick(void)
|
||||
{
|
||||
static int gpio[LEDS]={LED1, LED2, LED3, LASER};
|
||||
static int pos [LEDS]={ 0, 3, 6, 9};
|
||||
static int inc [LEDS]={ 1, 1, 1, 1};
|
||||
|
||||
static int vals[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 249};
|
||||
|
||||
int i;
|
||||
|
||||
for (i=0; i<LEDS; i++)
|
||||
{
|
||||
gpioPWM(gpio[i], vals[pos[i]]);
|
||||
|
||||
pos[i] += inc[i];
|
||||
|
||||
if ( (pos[i]>=(sizeof(vals)/4)) || (pos[i]<0) )
|
||||
{
|
||||
inc[i] = -inc[i];
|
||||
pos[i] += inc[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sonarLDRtick(void)
|
||||
{
|
||||
/* trigger a sonar reading */
|
||||
|
||||
gpioWrite(SONAR_TRIGGER, PI_ON);
|
||||
usleep(20);
|
||||
gpioWrite(SONAR_TRIGGER, PI_OFF);
|
||||
|
||||
/* trigger a LDR reading */
|
||||
|
||||
gpioSetMode(LDR, PI_OUTPUT); /* drain capacitor */
|
||||
|
||||
gpioWrite(LDR, PI_OFF);
|
||||
|
||||
usleep(200);
|
||||
|
||||
LDRrechargeTick = gpioTick();
|
||||
|
||||
gpioSetMode(LDR, PI_INPUT); /* start capacitor recharge */
|
||||
}
|
||||
|
||||
void motorTick(void)
|
||||
{
|
||||
static int gpio_in1[2]={MOTOR_A_IN1, MOTOR_B_IN1};
|
||||
static int gpio_in2[2]={MOTOR_A_IN2, MOTOR_B_IN2};
|
||||
static int speed [2]={ 80, 80};
|
||||
static int inc [2]={ -50, 50};
|
||||
|
||||
int i;
|
||||
char str[256];
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
speed[i]+=inc[i];
|
||||
|
||||
if (speed[i]<0)
|
||||
{
|
||||
gpioPWM(gpio_in1[i], -speed[i]);
|
||||
gpioPWM(gpio_in2[i], 0);
|
||||
if (speed[i] < -205) inc[i] = -inc[i];
|
||||
sprintf(str, "MOT%d IN1=%3d IN2=%3d", i+1, -speed[i], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioPWM(gpio_in2[i], speed[i]);
|
||||
gpioPWM(gpio_in1[i], 0);
|
||||
if (speed[i] > 205) inc[i] = -inc[i];
|
||||
sprintf(str, "MOT%d IN1=%3d IN2=%3d", i+1, 0, speed[i]);
|
||||
}
|
||||
if (i) putTTYstr(7, 1, str); else putTTYstr(5, 1, str);
|
||||
}
|
||||
}
|
||||
|
||||
/* loads of code to read/write i2c */
|
||||
|
||||
void selectDevice(int i2c, int addr, char * name)
|
||||
{
|
||||
if (ioctl(i2c, I2C_SLAVE, addr) < 0)
|
||||
{
|
||||
fprintf(stderr, "%s not present\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
void writeToDevice(int i2c, char * buf, int len)
|
||||
{
|
||||
static int reported = 0;
|
||||
if (write(i2c, buf, len) != len)
|
||||
{
|
||||
if (!reported)
|
||||
{
|
||||
fprintf(stderr, "Can't write to device\n");
|
||||
reported = 1;
|
||||
}
|
||||
}
|
||||
else reported = 0;
|
||||
}
|
||||
|
||||
void readADXL345(int i2c)
|
||||
{
|
||||
char buf[8];
|
||||
static int reported = 0;
|
||||
|
||||
selectDevice(i2c, ADXL345_I2C_ADDR, "ADXL345");
|
||||
|
||||
writeToDevice(i2c, "\x32", 1);
|
||||
|
||||
if (read(i2c, buf, 6) != 6)
|
||||
{
|
||||
if (!reported)
|
||||
{
|
||||
fprintf(stderr, "Unable to read from ADXL345\n");
|
||||
reported = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reported = 0;
|
||||
|
||||
ACC_ORIENTATION (
|
||||
((buf[1]<<8) | buf[0]),
|
||||
((buf[3]<<8) | buf[2]),
|
||||
((buf[5]<<8) | buf[4]) );
|
||||
}
|
||||
}
|
||||
|
||||
void readITG3200(int i2c)
|
||||
{
|
||||
char buf[8];
|
||||
static int reported = 0;
|
||||
|
||||
selectDevice(i2c, ITG3200_I2C_ADDR, "ITG3200");
|
||||
|
||||
writeToDevice(i2c, "\x1D", 1);
|
||||
|
||||
if (read(i2c, buf, 6) != 6)
|
||||
{
|
||||
if (!reported)
|
||||
{
|
||||
fprintf(stderr, "Unable to read from ITG3200\n");
|
||||
reported = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reported = 0;
|
||||
|
||||
GYRO_ORIENTATION (
|
||||
((buf[0]<<8) | buf[1]),
|
||||
((buf[2]<<8) | buf[3]),
|
||||
((buf[4]<<8) | buf[5]) );
|
||||
}
|
||||
}
|
||||
|
||||
int initI2Cdevices(void)
|
||||
{
|
||||
int i2c;
|
||||
|
||||
if ((i2c = open("/dev/i2c-0", O_RDWR)) < 0)
|
||||
{
|
||||
perror("Failed to open i2c bus");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialise ADXL345 */
|
||||
|
||||
selectDevice(i2c, ADXL345_I2C_ADDR, "ADXL345");
|
||||
|
||||
writeToDevice(i2c, "\x2d\x00", 2);
|
||||
writeToDevice(i2c, "\x2d\x10", 2);
|
||||
writeToDevice(i2c, "\x2d\x08", 2);
|
||||
writeToDevice(i2c, "\x31\x00", 2);
|
||||
writeToDevice(i2c, "\x31\x0b", 2);
|
||||
|
||||
/* initialise ITG3200 */
|
||||
|
||||
selectDevice(i2c, ITG3200_I2C_ADDR, "ITG3200");
|
||||
|
||||
writeToDevice(i2c, "\x16\b00011000", 2);
|
||||
|
||||
return i2c;
|
||||
}
|
||||
|
||||
/* an attached IMU (GY-85) supplies orientation information which
|
||||
is used to position the servos */
|
||||
|
||||
float estimateAngle(int acc, int gyro, float oldAng, int elapsed)
|
||||
{
|
||||
float angleAcc, angleInc, estAngle;
|
||||
float secs;
|
||||
|
||||
secs = (float) elapsed / 1e6f;
|
||||
|
||||
angleAcc = (float) acc * 90.0f / 256.0f;
|
||||
|
||||
angleInc = (float) gyro * secs * 2000.0f / 32768.0f;
|
||||
|
||||
estAngle = 0.75 * (oldAng + angleInc) + 0.25 * angleAcc;
|
||||
|
||||
return estAngle;
|
||||
}
|
||||
|
||||
void servoTick(void)
|
||||
{
|
||||
static int wid1=1500, wid2=1500, wid3=1500;
|
||||
static int inc1=50, inc2=75, inc3=100;
|
||||
|
||||
gpioServo(SERVO1, wid1);
|
||||
gpioServo(SERVO2, wid2);
|
||||
gpioServo(SERVO3, wid3);
|
||||
|
||||
wid1+=inc1; if ((wid1<1000) || (wid1>2000)) {inc1 = -inc1; wid1+=inc1;}
|
||||
wid2+=inc2; if ((wid2<1000) || (wid2>2000)) {inc2 = -inc2; wid2+=inc2;}
|
||||
wid3+=inc3; if ((wid3<1000) || (wid3>2000)) {inc3 = -inc3; wid3+=inc3;}
|
||||
}
|
||||
|
||||
void i2cTick(void)
|
||||
{
|
||||
static int inited = 0;
|
||||
static int calibrated = 0;
|
||||
static int calibrations = 0;
|
||||
static int accCalibX = 0, accCalibY = 0, accCalibZ = 0;
|
||||
static int gyroCalibX = 0, gyroCalibY = 0, gyroCalibZ = 0;
|
||||
static int i2c;
|
||||
static float X=0.0, Y=0.0, Z=0.0;
|
||||
|
||||
static uint32_t lastTick;
|
||||
|
||||
uint32_t tick;
|
||||
int elapsed;
|
||||
int pulse;
|
||||
char str[256];
|
||||
|
||||
if (inited)
|
||||
{
|
||||
tick = gpioTick();
|
||||
elapsed = tick - lastTick;
|
||||
lastTick = tick;
|
||||
|
||||
readADXL345(i2c);
|
||||
readITG3200(i2c);
|
||||
|
||||
if (calibrated)
|
||||
{
|
||||
X = estimateAngle(
|
||||
rawAcc[ROLL], rawGyr[ROLL] -gyroCalibX, X, elapsed);
|
||||
|
||||
Y = estimateAngle(
|
||||
rawAcc[PITCH], rawGyr[PITCH] - gyroCalibY, Y, elapsed);
|
||||
|
||||
Z = estimateAngle(
|
||||
rawAcc[YAW], rawGyr[YAW] - gyroCalibZ, Z, elapsed);
|
||||
|
||||
pulse = 1500 + (Y * 1000 / 90);
|
||||
if (pulse < 500) pulse = 500;
|
||||
if (pulse > 2500) pulse = 2500;
|
||||
gpioServo(SERVO1, pulse);
|
||||
|
||||
pulse = 1500 - (X * 500 / 90);
|
||||
if (pulse < 1000) pulse = 1000;
|
||||
if (pulse > 2000) pulse = 2000;
|
||||
gpioServo(SERVO2, pulse);
|
||||
|
||||
/* prefer Z but that doesn't change much */
|
||||
pulse = 1500 - (Y * 500 / 90);
|
||||
if (pulse < 800) pulse = 800;
|
||||
if (pulse > 2200) pulse = 2200;
|
||||
gpioServo(SERVO3, pulse);
|
||||
|
||||
sprintf(str, "X=%4.0f Y=%4.0f Z=%4.0f ", X, Y, Z);
|
||||
putTTYstr(1, 1, str);
|
||||
}
|
||||
else
|
||||
{
|
||||
accCalibX+=rawAcc[ROLL];
|
||||
accCalibY+=rawAcc[PITCH];
|
||||
accCalibZ+=rawAcc[YAW];
|
||||
|
||||
gyroCalibX+=rawGyr[ROLL];
|
||||
gyroCalibY+=rawGyr[PITCH];
|
||||
gyroCalibZ+=rawGyr[YAW];
|
||||
|
||||
if (++calibrations >= CALIBRATIONS)
|
||||
{
|
||||
accCalibX /= CALIBRATIONS;
|
||||
accCalibY /= CALIBRATIONS;
|
||||
accCalibZ /= CALIBRATIONS;
|
||||
|
||||
gyroCalibX /= CALIBRATIONS;
|
||||
gyroCalibY /= CALIBRATIONS;
|
||||
gyroCalibZ /= CALIBRATIONS;
|
||||
|
||||
calibrated = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c = initI2Cdevices();
|
||||
|
||||
gpioServo(SERVO1, 1500);
|
||||
gpioServo(SERVO2, 1500);
|
||||
gpioServo(SERVO3, 1500);
|
||||
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void sonarAlert(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
static uint32_t startTick;
|
||||
|
||||
int diffTick;
|
||||
char str[256];
|
||||
|
||||
if (level == PI_ON)
|
||||
{
|
||||
startTick = tick;
|
||||
}
|
||||
else if (level == PI_OFF)
|
||||
{
|
||||
diffTick = tick - startTick;
|
||||
|
||||
if (diffTick < 26100)
|
||||
{
|
||||
sprintf(str, "Sonar %3d cms", (diffTick+29)/58);
|
||||
putTTYstr(15, 1, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LDRalert(int pin, int level, uint32_t tick)
|
||||
{
|
||||
int diffTick;
|
||||
char str[256];
|
||||
|
||||
if (level == PI_ON)
|
||||
{
|
||||
diffTick = tick - LDRrechargeTick;
|
||||
|
||||
sprintf(str, "LDR %4d micros", diffTick);
|
||||
putTTYstr(17, 1, str);
|
||||
}
|
||||
}
|
||||
|
||||
void launchpadAlert(int pin, int level, uint32_t tick)
|
||||
{
|
||||
static int inited = 0, lastTick, lastPulseLen;
|
||||
|
||||
int pulseLen, pulseDif;
|
||||
|
||||
if (inited)
|
||||
{
|
||||
pulseLen = tick - lastTick;
|
||||
lastTick = tick;
|
||||
|
||||
if (level==0)
|
||||
{
|
||||
if (lastPulseLen)
|
||||
{
|
||||
pulseDif = pulseLen - lastPulseLen;
|
||||
|
||||
/* allow for wrap around */
|
||||
if (pulseDif < 0) pulseDif += 1096;
|
||||
|
||||
/* now centre around expected value */
|
||||
pulseDif -= 33;
|
||||
|
||||
if (pulseDif < 0) pulseDif = -pulseDif;
|
||||
|
||||
launchpadPulses++;
|
||||
|
||||
if (pulseDif <= 5)
|
||||
{
|
||||
launchpad5++;
|
||||
}
|
||||
else if (pulseDif <= 10)
|
||||
{
|
||||
launchpad10++;
|
||||
}
|
||||
else if (pulseDif <= 15)
|
||||
{
|
||||
launchpad15++;
|
||||
}
|
||||
else
|
||||
{
|
||||
launchpadOutRange++;
|
||||
launchpadErr = pulseDif;
|
||||
}
|
||||
}
|
||||
lastPulseLen = pulseLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lastTick = tick;
|
||||
lastPulseLen = 0;
|
||||
|
||||
launchpadPulses = 0;
|
||||
launchpad5 = 0;
|
||||
launchpad10 = 0;
|
||||
launchpad15 = 0;
|
||||
launchpadOutRange = 0;
|
||||
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void putTTY(char * buf)
|
||||
{
|
||||
write(1, buf, strlen(buf));
|
||||
}
|
||||
|
||||
void putTTYstr(int row, int col, char * buf)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
sprintf(str, "\033[%d;%dH%s", row, col, buf);
|
||||
|
||||
putTTY(str);
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/*
|
||||
This version is for pigpio version 3+
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
|
||||
/*
|
||||
This software converts pigpio notification reports
|
||||
into a VCD format understood by GTKWave.
|
||||
*/
|
||||
|
||||
#define RS (sizeof(gpioReport_t))
|
||||
|
||||
static char * timeStamp()
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
struct timeval now;
|
||||
struct tm tmp;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
localtime_r(&now.tv_sec, &tmp);
|
||||
strftime(buf, sizeof(buf), "%F %T", &tmp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int symbol(int bit)
|
||||
{
|
||||
if (bit < 26) return ('A' + bit);
|
||||
else return ('a' + bit - 26);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int b, r, v;
|
||||
uint32_t t0;
|
||||
uint32_t lastLevel, changed;
|
||||
|
||||
gpioReport_t report;
|
||||
|
||||
r=read(STDIN_FILENO, &report, RS);
|
||||
|
||||
if (r != RS) exit(-1);
|
||||
|
||||
printf("$date %s $end\n", timeStamp());
|
||||
printf("$version pig2vcd V1 $end\n");
|
||||
printf("$timescale 1 us $end\n");
|
||||
printf("$scope module top $end\n");
|
||||
|
||||
for (b=0; b<32; b++)
|
||||
printf("$var wire 1 %c %d $end\n", symbol(b), b);
|
||||
|
||||
printf("$upscope $end\n");
|
||||
printf("$enddefinitions $end\n");
|
||||
|
||||
t0 = report.tick;
|
||||
lastLevel =0;
|
||||
|
||||
while ((r=read(STDIN_FILENO, &report, RS)) == RS)
|
||||
{
|
||||
if (report.level != lastLevel)
|
||||
{
|
||||
printf("#%u\n", report.tick - t0);
|
||||
|
||||
changed = report.level ^ lastLevel;
|
||||
|
||||
lastLevel = report.level;
|
||||
|
||||
for (b=0; b<32; b++)
|
||||
{
|
||||
if (changed & (1<<b))
|
||||
{
|
||||
if (report.level & (1<<b)) v='1'; else v='0';
|
||||
|
||||
printf("%c%c\n", v, symbol(b));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/*
|
||||
This version is for pigpio version 4+
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
#include "command.h"
|
||||
|
||||
/*
|
||||
This program starts the pigpio library as a daemon.
|
||||
*/
|
||||
|
||||
static unsigned bufferSizeMilliseconds = PI_DEFAULT_BUFFER_MILLIS;
|
||||
static unsigned clockMicros = PI_DEFAULT_CLK_MICROS;
|
||||
static unsigned clockPeripheral = PI_DEFAULT_CLK_PERIPHERAL;
|
||||
static unsigned clockSource = PI_DEFAULT_CLK_SOURCE;
|
||||
static unsigned ifFlags = PI_DEFAULT_IF_FLAGS;
|
||||
static unsigned DMAchannelChannel = PI_DEFAULT_DMA_CHANNEL;
|
||||
static unsigned socketPort = PI_DEFAULT_SOCKET_PORT;
|
||||
|
||||
static FILE * errFifo;
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr, "\n" \
|
||||
"Usage: sudo pigpiod [OPTION] ...\n" \
|
||||
" -b value, gpio sample buffer in milliseconds, default 120\n" \
|
||||
" -d value, DMA channel, 0-14, default 14\n" \
|
||||
" -f, disable fifo interface, default enabled\n" \
|
||||
" -k, disable socket interface, default enabled\n" \
|
||||
" -p value, socket port, 1024-32000, default 8888\n" \
|
||||
" -s value, sample rate, 1, 2, 4, 5, 8, or 10, default 5\n" \
|
||||
" -t value, clock peripheral, 0=PWM 1=PCM, default PCM\n" \
|
||||
" -u value, clock source, 0=OSC 1=PLLD, default PLLD\n" \
|
||||
"EXAMPLE\n" \
|
||||
"sudo pigpiod -s 2 -b 200 -f\n" \
|
||||
" Set a sample rate of 2 microseconds with a 200 millisecond\n" \
|
||||
" buffer. Disable the fifo interface.\n" \
|
||||
"\n");
|
||||
}
|
||||
|
||||
static void initOpts(int argc, char *argv[])
|
||||
{
|
||||
int i, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "b:d:fkp:s:t:u:")) != -1)
|
||||
{
|
||||
i = -1;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 'b':
|
||||
i = atoi(optarg);
|
||||
if ((i >= PI_BUF_MILLIS_MIN) && (i <= PI_BUF_MILLIS_MAX))
|
||||
bufferSizeMilliseconds = i;
|
||||
else cmdFatal("invalid -b option (%d)", i);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
i = atoi(optarg);
|
||||
if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_DMA_CHANNEL))
|
||||
DMAchannelChannel = i;
|
||||
else cmdFatal("invalid -d option (%d)", i);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
ifFlags |= PI_DISABLE_FIFO_IF;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
ifFlags |= PI_DISABLE_SOCK_IF;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
i = atoi(optarg);
|
||||
if ((i >= PI_MIN_SOCKET_PORT) && (i <= PI_MAX_SOCKET_PORT))
|
||||
socketPort = i;
|
||||
else cmdFatal("invalid -p option (%d)", i);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
i = atoi(optarg);
|
||||
|
||||
switch(i)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 5:
|
||||
case 8:
|
||||
case 10:
|
||||
clockMicros = i;
|
||||
break;
|
||||
|
||||
default:
|
||||
cmdFatal("invalid -s option (%d)", i);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
i = atoi(optarg);
|
||||
if ((i >= PI_CLOCK_PWM) && (i <= PI_CLOCK_PCM))
|
||||
clockPeripheral = i;
|
||||
else cmdFatal("invalid -t option (%d)", i);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
i = atoi(optarg);
|
||||
if ((i >= PI_CLOCK_OSC) && (i <= PI_CLOCK_PLLD))
|
||||
clockSource = i;
|
||||
else cmdFatal("invalid -u option (%d)", i);
|
||||
break;
|
||||
|
||||
default: /* '?' */
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void terminate(int signum)
|
||||
{
|
||||
/* only registered for SIGHUP/SIGTERM */
|
||||
|
||||
gpioTerminate();
|
||||
|
||||
fprintf(errFifo, "SIGHUP/SIGTERM received\n");
|
||||
|
||||
fflush(NULL);
|
||||
|
||||
fclose(errFifo);
|
||||
|
||||
unlink(PI_ERRFIFO);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
pid_t pid;
|
||||
int flags;
|
||||
|
||||
/* Fork off the parent process */
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) { exit(EXIT_FAILURE); }
|
||||
|
||||
/* If we got a good PID, then we can exit the parent process. */
|
||||
|
||||
if (pid > 0) { exit(EXIT_SUCCESS); }
|
||||
|
||||
/* Change the file mode mask */
|
||||
|
||||
umask(0);
|
||||
|
||||
/* Open any logs here */
|
||||
|
||||
/* NONE */
|
||||
|
||||
/* Create a new SID for the child process */
|
||||
|
||||
if (setsid() < 0) cmdFatal("setsid failed (%m)");
|
||||
|
||||
/* Change the current working directory */
|
||||
|
||||
if ((chdir("/")) < 0) cmdFatal("chdir failed (%m)");
|
||||
|
||||
/* check command line parameters */
|
||||
|
||||
initOpts(argc, argv);
|
||||
|
||||
/* Close out the standard file descriptors */
|
||||
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
|
||||
/* configure library */
|
||||
|
||||
gpioCfgBufferSize(bufferSizeMilliseconds);
|
||||
|
||||
gpioCfgClock(clockMicros, clockPeripheral, clockSource);
|
||||
|
||||
gpioCfgInterfaces(ifFlags);
|
||||
|
||||
gpioCfgDMAchannel(DMAchannelChannel);
|
||||
|
||||
gpioCfgSocketPort(socketPort);
|
||||
|
||||
/* start library */
|
||||
|
||||
if (gpioInitialise()< 0) cmdFatal("Can't initialise pigpio library");
|
||||
|
||||
/* create pipe for error reporting */
|
||||
|
||||
unlink(PI_ERRFIFO);
|
||||
|
||||
mkfifo(PI_ERRFIFO, 0664);
|
||||
|
||||
if (chmod(PI_ERRFIFO, 0664) < 0)
|
||||
cmdFatal("chmod %s failed (%m)", PI_ERRFIFO);
|
||||
|
||||
errFifo = freopen(PI_ERRFIFO, "w+", stderr);
|
||||
|
||||
if (errFifo)
|
||||
{
|
||||
/* set stderr non-blocking */
|
||||
|
||||
flags = fcntl(fileno(errFifo), F_GETFL, 0);
|
||||
fcntl(fileno(errFifo), F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
/* request SIGHUP/SIGTERM from libarary for termination */
|
||||
|
||||
gpioSetSignalFunc(SIGHUP, terminate);
|
||||
gpioSetSignalFunc(SIGTERM, terminate);
|
||||
|
||||
/* sleep forever */
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* cat /dev/pigerr to view daemon errors */
|
||||
|
||||
sleep(5);
|
||||
|
||||
fflush(errFifo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "freopen failed (%m)");
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
/*
|
||||
This version is for pigpio version 3+
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
#include "command.h"
|
||||
|
||||
/*
|
||||
This program provides a socket interface
|
||||
to the commands available from pigpio.
|
||||
*/
|
||||
|
||||
int main(int argc , char *argv[])
|
||||
{
|
||||
int sock, r, idx, port;
|
||||
struct sockaddr_in server;
|
||||
cmdCmd_t cmd;
|
||||
char * portStr, * addrStr;
|
||||
char buf[128];
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sock != -1)
|
||||
{
|
||||
portStr = getenv(PI_ENVPORT);
|
||||
|
||||
if (portStr) port = atoi(portStr);
|
||||
else port = PI_DEFAULT_SOCKET_PORT;
|
||||
|
||||
addrStr = getenv(PI_ENVADDR);
|
||||
|
||||
if (!addrStr) addrStr="127.0.0.1";
|
||||
|
||||
server.sin_addr.s_addr = inet_addr(addrStr);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == 0)
|
||||
{
|
||||
switch(argc)
|
||||
{
|
||||
case 1:
|
||||
exit(0);
|
||||
|
||||
case 2:
|
||||
sprintf(buf, "%10s", argv[1]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
sprintf(buf, "%10s %10s", argv[1], argv[2]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
sprintf(buf, "%10s %10s %10s", argv[1], argv[2], argv[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
cmdFatal("what?");
|
||||
}
|
||||
|
||||
if ((idx=cmdParse(buf, &cmd)) >= 0)
|
||||
{
|
||||
if (send(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t))
|
||||
{
|
||||
if (recv(sock, &cmd, sizeof(cmdCmd_t), 0) == sizeof(cmdCmd_t))
|
||||
{
|
||||
switch (cmdInfo[idx].rv)
|
||||
{
|
||||
case 0:
|
||||
r = cmd.res;
|
||||
if (r < 0) cmdFatal("ERROR: %s", cmdErrStr(r));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 2:
|
||||
r = cmd.res;
|
||||
if (r < 0) cmdFatal("ERROR: %s", cmdErrStr(r));
|
||||
else printf("%d\n", r);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
printf("%08X\n", cmd.res);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
printf("%u\n", cmd.res);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
printf(cmdUsage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else cmdFatal("recv failed, %m");
|
||||
}
|
||||
else cmdFatal("send failed, %m");
|
||||
}
|
||||
else cmdFatal("what?");
|
||||
}
|
||||
else cmdFatal("connect failed, %m");
|
||||
|
||||
close(sock);
|
||||
}
|
||||
else cmdFatal("socket failed, %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue