/* gcc -o x_pigpio x_pigpio.c -lpigpio -lrt -lpthread sudo ./x_pigpio *** WARNING ************************************************ * * * All the tests make extensive use of gpio 25 (pin 22). * * Ensure that either nothing or just a LED is connected to * * gpio 25 before running any of the tests. * * * * Some tests are statistical in nature and so may on * * occasion fail. Repeated failures on the same test or * * many failures in a group of tests indicate a problem. * ************************************************************ */ #include #include #include #include #include #include #include #include #include "pigpio.h" #define USERDATA 18249013 #define GPIO 25 void CHECK(int t, int st, int got, int expect, int pc, char *desc) { if ((got >= (((1E2-pc)*expect)/1E2)) && (got <= (((1E2+pc)*expect)/1E2))) { printf("TEST %2d.%-2d PASS (%s: %d)\n", t, st, desc, expect); } else { fprintf(stderr, "TEST %2d.%-2d FAILED got %d (%s: %d)\n", t, st, got, desc, expect); } } void t0() { printf("Version.\n"); printf("pigpio version %d.\n", gpioVersion()); printf("Hardware revision %d.\n", gpioHardwareRevision()); } void t1() { int v; printf("Mode/PUD/read/write tests.\n"); gpioSetMode(GPIO, PI_INPUT); v = gpioGetMode(GPIO); CHECK(1, 1, v, 0, 0, "set mode, get mode"); gpioSetPullUpDown(GPIO, PI_PUD_UP); v = gpioRead(GPIO); CHECK(1, 2, v, 1, 0, "set pull up down, read"); gpioSetPullUpDown(GPIO, PI_PUD_DOWN); v = gpioRead(GPIO); CHECK(1, 3, v, 0, 0, "set pull up down, read"); gpioWrite(GPIO, PI_LOW); v = gpioGetMode(GPIO); CHECK(1, 4, v, 1, 0, "write, get mode"); v = gpioRead(GPIO); CHECK(1, 5, v, 0, 0, "read"); gpioWrite(GPIO, PI_HIGH); v = gpioRead(GPIO); CHECK(1, 6, v, 1, 0, "write, read"); } int t2_count; void t2cb(int gpio, int level, uint32_t tick) { t2_count++; } void t2() { int dc, f, r, rr, oc; printf("PWM dutycycle/range/frequency tests.\n"); gpioSetPWMrange(GPIO, 255); gpioSetPWMfrequency(GPIO, 0); f = gpioGetPWMfrequency(GPIO); CHECK(2, 1, f, 10, 0, "set PWM range, set/get PWM frequency"); t2_count=0; gpioSetAlertFunc(GPIO, t2cb); gpioPWM(GPIO, 0); dc = gpioGetPWMdutycycle(GPIO); CHECK(2, 2, dc, 0, 0, "get PWM dutycycle"); time_sleep(0.5); /* allow old notifications to flush */ oc = t2_count; time_sleep(2); f = t2_count - oc; CHECK(2, 3, f, 0, 0, "set PWM dutycycle, callback"); gpioPWM(GPIO, 128); dc = gpioGetPWMdutycycle(GPIO); CHECK(2, 4, dc, 128, 0, "get PWM dutycycle"); oc = t2_count; time_sleep(2); f = t2_count - oc; CHECK(2, 5, f, 40, 5, "set PWM dutycycle, callback"); gpioSetPWMfrequency(GPIO, 100); f = gpioGetPWMfrequency(GPIO); CHECK(2, 6, f, 100, 0, "set/get PWM frequency"); oc = t2_count; time_sleep(2); f = t2_count - oc; CHECK(2, 7, f, 400, 1, "callback"); gpioSetPWMfrequency(GPIO, 1000); f = gpioGetPWMfrequency(GPIO); CHECK(2, 8, f, 1000, 0, "set/get PWM frequency"); oc = t2_count; time_sleep(2); f = t2_count - oc; CHECK(2, 9, f, 4000, 1, "callback"); r = gpioGetPWMrange(GPIO); CHECK(2, 10, r, 255, 0, "get PWM range"); rr = gpioGetPWMrealRange(GPIO); CHECK(2, 11, rr, 200, 0, "get PWM real range"); gpioSetPWMrange(GPIO, 2000); r = gpioGetPWMrange(GPIO); CHECK(2, 12, r, 2000, 0, "set/get PWM range"); rr = gpioGetPWMrealRange(GPIO); CHECK(2, 13, rr, 200, 0, "get PWM real range"); gpioPWM(GPIO, 0); } int t3_val; int t3_reset; int t3_count; uint32_t t3_tick; float t3_on; float t3_off; void t3cbf(int gpio, int level, uint32_t tick, void *userdata) { static int unreported = 1; uint32_t td; int *val; val = userdata; if (*val != USERDATA) { if (unreported) { fprintf ( stderr, "unexpected userdata %d (expected %d)\n", *val, USERDATA ); } unreported = 0; } if (t3_reset) { t3_count = 0; t3_on = 0.0; t3_off = 0.0; t3_reset = 0; } else { td = tick - t3_tick; if (level == 0) t3_on += td; else t3_off += td; } t3_count ++; t3_tick = tick; } void t3() { int f, rr; float on, off; int t, v; int pw[3]={500, 1500, 2500}; int dc[4]={20, 40, 60, 80}; printf("PWM/Servo pulse accuracy tests.\n"); t3_val = USERDATA; t3_reset=1; t3_count=0; t3_tick=0; t3_on=0.0; t3_off=0.0; gpioSetAlertFuncEx(GPIO, t3cbf, &t3_val); /* test extended alert */ for (t=0; t<3; t++) { gpioServo(GPIO, pw[t]); v = gpioGetServoPulsewidth(GPIO); CHECK(3, t+t+1, v, pw[t], 0, "get servo pulsewidth"); time_sleep(1); t3_reset = 1; time_sleep(4); on = t3_on; off = t3_off; CHECK(3, t+t+2, (1E3*(on+off))/on, 2E7/pw[t], 1, "set servo pulsewidth"); } gpioServo(GPIO, 0); gpioSetPWMfrequency(GPIO, 1000); f = gpioGetPWMfrequency(GPIO); CHECK(3, 7, f, 1000, 0, "set/get PWM frequency"); rr = gpioSetPWMrange(GPIO, 100); CHECK(3, 8, rr, 200, 0, "set PWM range"); for (t=0; t<4; t++) { gpioPWM(GPIO, dc[t]); v = gpioGetPWMdutycycle(GPIO); CHECK(3, t+t+9, v, dc[t], 0, "get PWM dutycycle"); time_sleep(1); t3_reset = 1; time_sleep(2); on = t3_on; off = t3_off; CHECK(3, t+t+10, (1E3*on)/(on+off), 1E1*dc[t], 1, "set PWM dutycycle"); } gpioPWM(GPIO, 0); } void t4() { int h, e, f, n, s, b, l, seq_ok, toggle_ok; gpioReport_t r; char p[32]; printf("Pipe notification tests.\n"); gpioSetPWMfrequency(GPIO, 0); gpioPWM(GPIO, 0); gpioSetPWMrange(GPIO, 100); h = gpioNotifyOpen(); e = gpioNotifyBegin(h, (1< 0) text[c] = 0; CHECK(5, 11, strcmp(TEXT, text), 0, 0, "wave tx busy, serial read"); e = gpioSerialReadClose(GPIO); CHECK(5, 12, e, 0, 0, "serial read close"); c = gpioWaveGetMicros(); CHECK(5, 13, c, 6158148, 0, "wave get micros"); c = gpioWaveGetHighMicros(); CHECK(5, 14, c, 6158148, 0, "wave get high micros"); c = gpioWaveGetMaxMicros(); CHECK(5, 15, c, 1800000000, 0, "wave get max micros"); c = gpioWaveGetPulses(); CHECK(5, 16, c, 3405, 0, "wave get pulses"); c = gpioWaveGetHighPulses(); CHECK(5, 17, c, 3405, 0, "wave get high pulses"); c = gpioWaveGetMaxPulses(); CHECK(5, 18, c, 12000, 0, "wave get max pulses"); c = gpioWaveGetCbs(); CHECK(5, 19, c, 6810, 0, "wave get cbs"); c = gpioWaveGetHighCbs(); CHECK(5, 20, c, 6810, 0, "wave get high cbs"); c = gpioWaveGetMaxCbs(); CHECK(5, 21, c, 25016, 0, "wave get max cbs"); } int t6_count; int t6_on; uint32_t t6_on_tick; void t6cbf(int gpio, int level, uint32_t tick) { if (level == 1) { t6_on_tick = tick; t6_count++; } else { if (t6_on_tick) t6_on += (tick - t6_on_tick); } } void t6() { int tp, t, p; printf("Trigger tests\n"); gpioWrite(GPIO, PI_LOW); tp = 0; t6_count=0; t6_on=0; t6_on_tick=0; gpioSetAlertFunc(GPIO, t6cbf); for (t=0; t<5; t++) { time_sleep(0.1); p = 10 + (t*10); tp += p; gpioTrigger(GPIO, p, 1); } time_sleep(0.2); CHECK(6, 1, t6_count, 5, 0, "gpio trigger count"); CHECK(6, 2, t6_on, tp, 25, "gpio trigger pulse length"); } int t7_count; void t7cbf(int gpio, int level, uint32_t tick) { if (level == PI_TIMEOUT) t7_count++; } void t7() { int c, oc; printf("Watchdog tests.\n"); t7_count=0; /* type of edge shouldn't matter for watchdogs */ gpioSetAlertFunc(GPIO, t7cbf); gpioSetWatchdog(GPIO, 10); /* 10 ms, 100 per second */ time_sleep(0.5); oc = t7_count; time_sleep(2); c = t7_count - oc; CHECK(7, 1, c, 200, 1, "set watchdog on count"); gpioSetWatchdog(GPIO, 0); /* 0 switches watchdog off */ time_sleep(0.5); oc = t7_count; time_sleep(2); c = t7_count - oc; CHECK(7, 2, c, 0, 1, "set watchdog off count"); } void t8() { int v; printf("Bank read/write tests.\n"); gpioWrite(GPIO, 0); v = gpioRead_Bits_0_31() & (1<= 0) text[b] = 0; CHECK(10, 7, strcmp(TEXT, text), 0, 0, "serial read"); b = serReadByte(h); CHECK(10, 8, b, 0xAA, 0, "serial read byte"); b = serReadByte(h); CHECK(10, 9, b, 0x55, 0, "serial read byte"); b = serReadByte(h); CHECK(10, 10, b, 0x00, 0, "serial read byte"); b = serReadByte(h); CHECK(10, 11, b, 0xFF, 0, "serial read byte"); b = serDataAvailable(h); CHECK(10, 12, b, 0, 0, "serial data availabe"); e = serClose(h); CHECK(10, 13, e, 0, 0, "serial close"); } void tb() { int h, e, b, len; char *exp; char buf[128]; printf("SMBus / I2C tests."); /* this test requires an ADXL345 on I2C bus 1 addr 0x53 */ h = i2cOpen(1, 0x53, 0); CHECK(11, 1, h, 0, 0, "i2cOpen"); e = i2cWriteDevice(h, "\x00", 1); /* move to known register */ CHECK(11, 2, e, 0, 0, "i2cWriteDevice"); b = i2cReadDevice(h, buf, 1); CHECK(11, 3, b, 1, 0, "i2cReadDevice"); CHECK(11, 4, buf[0], 0xE5, 0, "i2cReadDevice"); b = i2cReadByte(h); CHECK(11, 5, b, 0xE5, 0, "i2cReadByte"); b = i2cReadByteData(h, 0); CHECK(11, 6, b, 0xE5, 0, "i2cReadByteData"); b = i2cReadByteData(h, 48); CHECK(11, 7, b, 2, 0, "i2cReadByteData"); exp = "\x1D[aBcDeFgHjKM]"; len = strlen(exp); e = i2cWriteDevice(h, exp, len); CHECK(11, 8, e, 0, 0, "i2cWriteDevice"); e = i2cWriteDevice(h, "\x1D", 1); b = i2cReadDevice(h, buf, len-1); CHECK(11, 9, b, len-1, 0, "i2cReadDevice"); CHECK(11, 10, strncmp(buf, exp+1, len-1), 0, 0, "i2cReadDevice"); if (strncmp(buf, exp+1, len-1)) printf("got [%.*s] expected [%.*s]\n", len-1, buf, len-1, exp+1); e = i2cWriteByteData(h, 0x1d, 0xAA); CHECK(11, 11, e, 0, 0, "i2cWriteByteData"); b = i2cReadByteData(h, 0x1d); CHECK(11, 12, b, 0xAA, 0, "i2cReadByteData"); e = i2cWriteByteData(h, 0x1d, 0x55); CHECK(11, 13, e, 0, 0, "i2cWriteByteData"); b = i2cReadByteData(h, 0x1d); CHECK(11, 14, b, 0x55, 0, "i2cReadByteData"); exp = "[1234567890#]"; len = strlen(exp); e = i2cWriteBlockData(h, 0x1C, exp, len); CHECK(11, 15, e, 0, 0, "i2c writeBlockData"); e = i2cWriteDevice(h, "\x1D", 1); b = i2cReadDevice(h, buf, len); CHECK(11, 16, b, len, 0, "i2cReadDevice"); CHECK(11, 17, strncmp(buf, exp, len), 0, 0, "i2cReadDevice"); if (strncmp(buf, exp, len)) printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); b = i2cReadI2CBlockData(h, 0x1D, buf, len); CHECK(11, 18, b, len, 0, "i2cReadI2CBlockData"); CHECK(11, 19, strncmp(buf, exp, len), 0, 0, "i2cReadI2CBlockData"); if (strncmp(buf, exp, len)) printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); exp = "(-+=;:,<>!%)"; len = strlen(exp); e = i2cWriteI2CBlockData(h, 0x1D, exp, len); CHECK(11, 20, e, 0, 0, "i2cWriteI2CBlockData"); b = i2cReadI2CBlockData(h, 0x1D, buf, len); CHECK(11, 21, b, len, 0, "i2cReadI2CBlockData"); CHECK(11, 22, strncmp(buf, exp, len), 0, 0, "i2cReadI2CBlockData"); if (strncmp(buf, exp, len)) printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); e = i2cClose(h); CHECK(11, 23, e, 0, 0, "i2cClose"); } void tc() { int h, x, b, e; char txBuf[8], rxBuf[8]; printf("SPI tests."); /* this test requires a MCP3202 on SPI channel 1 */ h = spiOpen(1, 50000, 0); CHECK(12, 1, h, 0, 0, "spiOpen"); sprintf(txBuf, "\x01\x80"); for (x=0; x<5; x++) { b = spiXfer(h, txBuf, rxBuf, 3); CHECK(12, 2, b, 3, 0, "spiXfer"); if (b == 3) { time_sleep(1.0); printf("%d ", ((rxBuf[1]&0x0F)*256)|rxBuf[2]); } } e = spiClose(h); CHECK(12, 99, e, 0, 0, "spiClose"); } int main(int argc, char *argv[]) { int i, t, c, status; char test[64]; if (argc > 1) { t = 0; for (i=0; i