/* gcc -Wall -pthread -o x_pigpiod_if2 x_pigpiod_if2.c -lpigpiod_if2 ./x_pigpiod_if2 *** 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 <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include "pigpiod_if2.h" #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(int pi) { printf("\nTesting pigpiod C I/F 2\n"); printf("pigpio version %d.\n", get_pigpio_version(pi)); printf("Hardware revision %d.\n", get_hardware_revision(pi)); } void t1(int pi) { int v; printf("Mode/PUD/read/write tests.\n"); set_mode(pi, GPIO, PI_INPUT); v = get_mode(pi, GPIO); CHECK(1, 1, v, 0, 0, "set mode, get mode"); set_pull_up_down(pi, GPIO, PI_PUD_UP); v = gpio_read(pi, GPIO); CHECK(1, 2, v, 1, 0, "set pull up down, read"); set_pull_up_down(pi, GPIO, PI_PUD_DOWN); v = gpio_read(pi, GPIO); CHECK(1, 3, v, 0, 0, "set pull up down, read"); gpio_write(pi, GPIO, PI_LOW); v = get_mode(pi, GPIO); CHECK(1, 4, v, 1, 0, "write, get mode"); v = gpio_read(pi, GPIO); CHECK(1, 5, v, 0, 0, "read"); gpio_write(pi, GPIO, PI_HIGH); v = gpio_read(pi, GPIO); CHECK(1, 6, v, 1, 0, "write, read"); } int t2_count=0; void t2cb(int pi, unsigned gpio, unsigned level, uint32_t tick) { t2_count++; } void t2(int pi) { int dc, f, r, rr, oc, id; printf("PWM dutycycle/range/frequency tests.\n"); set_PWM_range(pi, GPIO, 255); set_PWM_frequency(pi, GPIO, 0); f = get_PWM_frequency(pi, GPIO); CHECK(2, 1, f, 10, 0, "set PWM range, set/get PWM frequency"); id = callback(pi, GPIO, EITHER_EDGE, t2cb); set_PWM_dutycycle(pi, GPIO, 0); dc = get_PWM_dutycycle(pi, 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"); set_PWM_dutycycle(pi, GPIO, 128); dc = get_PWM_dutycycle(pi, GPIO); CHECK(2, 4, dc, 128, 0, "get PWM dutycycle"); time_sleep(0.2); oc = t2_count; time_sleep(2); f = t2_count - oc; CHECK(2, 5, f, 40, 5, "set PWM dutycycle, callback"); set_PWM_frequency(pi, GPIO, 100); f = get_PWM_frequency(pi, GPIO); CHECK(2, 6, f, 100, 0, "set/get PWM frequency"); time_sleep(0.2); oc = t2_count; time_sleep(2); f = t2_count - oc; CHECK(2, 7, f, 400, 1, "callback"); set_PWM_frequency(pi, GPIO, 1000); f = get_PWM_frequency(pi, GPIO); CHECK(2, 8, f, 1000, 0, "set/get PWM frequency"); time_sleep(0.2); oc = t2_count; time_sleep(2); f = t2_count - oc; CHECK(2, 9, f, 4000, 1, "callback"); r = get_PWM_range(pi, GPIO); CHECK(2, 10, r, 255, 0, "get PWM range"); rr = get_PWM_real_range(pi, GPIO); CHECK(2, 11, rr, 200, 0, "get PWM real range"); set_PWM_range(pi, GPIO, 2000); r = get_PWM_range(pi, GPIO); CHECK(2, 12, r, 2000, 0, "set/get PWM range"); rr = get_PWM_real_range(pi, GPIO); CHECK(2, 13, rr, 200, 0, "get PWM real range"); set_PWM_dutycycle(pi, GPIO, 0); callback_cancel(id); } int t3_reset=1; int t3_count=0; uint32_t t3_tick=0; float t3_on=0.0; float t3_off=0.0; void t3cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) { uint32_t td; // printf("pi=%d g=%d l=%d t=%u\n", pi, gpio, level, tick); 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 pi) { int pw[3]={500, 1500, 2500}; int dc[4]={20, 40, 60, 80}; int f, rr, v; float on, off; int t, id; printf("PWM/Servo pulse accuracy tests.\n"); id = callback(pi, GPIO, EITHER_EDGE, t3cbf); for (t=0; t<3; t++) { set_servo_pulsewidth(pi, GPIO, pw[t]); v = get_servo_pulsewidth(pi, 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, (1000.0*(on+off))/on, 20000000.0/pw[t], 1, "set servo pulsewidth"); } set_servo_pulsewidth(pi, GPIO, 0); set_PWM_frequency(pi, GPIO, 1000); f = get_PWM_frequency(pi, GPIO); CHECK(3, 7, f, 1000, 0, "set/get PWM frequency"); rr = set_PWM_range(pi, GPIO, 100); CHECK(3, 8, rr, 200, 0, "set PWM range"); for (t=0; t<4; t++) { set_PWM_dutycycle(pi, GPIO, dc[t]); v = get_PWM_dutycycle(pi, 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, (1000.0*on)/(on+off), 10.0*dc[t], 1, "set PWM dutycycle"); } set_PWM_dutycycle(pi, GPIO, 0); callback_cancel(id); } void t4(int pi) { int h, e, f, n, s, b, l, seq_ok, toggle_ok; gpioReport_t r; char p[32]; printf("Pipe notification tests.\n"); set_PWM_frequency(pi, GPIO, 0); set_PWM_dutycycle(pi, GPIO, 0); set_PWM_range(pi, GPIO, 100); h = notify_open(pi); sprintf(p, "/dev/pigpio%d", h); f = open(p, O_RDONLY); e = notify_begin(pi, h, (1<<GPIO)); CHECK(4, 1, e, 0, 0, "notify open/begin"); set_PWM_dutycycle(pi, GPIO, 50); time_sleep(4); set_PWM_dutycycle(pi, GPIO, 0); e = notify_pause(pi, h); CHECK(4, 2, e, 0, 0, "notify pause"); e = notify_close(pi, h); CHECK(4, 3, e, 0, 0, "notify close"); n = 0; s = 0; l = 0; seq_ok = 1; toggle_ok = 1; while (1) { b = read(f, &r, 12); if (b == 12) { if (s != r.seqno) seq_ok = 0; if (n) if (l != (r.level&(1<<GPIO))) toggle_ok = 0; if (r.level&(1<<GPIO)) l = 0; else l = (1<<GPIO); s++; n++; // printf("%d %d %d %X\n", r.seqno, r.flags, r.tick, r.level); } else break; } close(f); CHECK(4, 4, seq_ok, 1, 0, "sequence numbers ok"); CHECK(4, 5, toggle_ok, 1, 0, "gpio toggled ok"); CHECK(4, 6, n, 80, 10, "number of notifications"); } int t5_count = 0; void t5cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) { t5_count++; } void t5(int pi) { int BAUD=4800; char *TEXT= "\n\ Now is the winter of our discontent\n\ Made glorious summer by this sun of York;\n\ And all the clouds that lour'd upon our house\n\ In the deep bosom of the ocean buried.\n\ Now are our brows bound with victorious wreaths;\n\ Our bruised arms hung up for monuments;\n\ Our stern alarums changed to merry meetings,\n\ Our dreadful marches to delightful measures.\n\ Grim-visaged war hath smooth'd his wrinkled front;\n\ And now, instead of mounting barded steeds\n\ To fright the souls of fearful adversaries,\n\ He capers nimbly in a lady's chamber\n\ To the lascivious pleasing of a lute.\n\ "; gpioPulse_t wf[] = { {1<<GPIO, 0, 10000}, {0, 1<<GPIO, 30000}, {1<<GPIO, 0, 60000}, {0, 1<<GPIO, 100000}, }; int e, oc, c, wid, id; char text[2048]; printf("Waveforms & serial read/write tests.\n"); id = callback(pi, GPIO, FALLING_EDGE, t5cbf); set_mode(pi, GPIO, PI_OUTPUT); e = wave_clear(pi); CHECK(5, 1, e, 0, 0, "callback, set mode, wave clear"); e = wave_add_generic(pi, 4, wf); CHECK(5, 2, e, 4, 0, "pulse, wave add generic"); wid = wave_create(pi); e = wave_send_repeat(pi, wid); if (e < 14) CHECK(5, 3, e, 9, 0, "wave tx repeat"); else CHECK(5, 3, e, 19, 0, "wave tx repeat"); oc = t5_count; time_sleep(5.05); c = t5_count - oc; CHECK(5, 4, c, 50, 2, "callback"); e = wave_tx_stop(pi); CHECK(5, 5, e, 0, 0, "wave tx stop"); e = bb_serial_read_open(pi, GPIO, BAUD, 8); CHECK(5, 6, e, 0, 0, "serial read open"); wave_clear(pi); e = wave_add_serial(pi, GPIO, BAUD, 8, 2, 5000000, strlen(TEXT), TEXT); CHECK(5, 7, e, 3405, 0, "wave clear, wave add serial"); wid = wave_create(pi); e = wave_send_once(pi, wid); if (e < 6964) CHECK(5, 8, e, 6811, 0, "wave tx start"); else CHECK(5, 8, e, 7116, 0, "wave tx start"); oc = t5_count; time_sleep(3); c = t5_count - oc; CHECK(5, 9, c, 0, 0, "callback"); oc = t5_count; while (wave_tx_busy(pi)) time_sleep(0.1); time_sleep(0.1); c = t5_count - oc; CHECK(5, 10, c, 1702, 0, "wave tx busy, callback"); c = bb_serial_read(pi, GPIO, text, sizeof(text)-1); if (c > 0) text[c] = 0; /* null terminate string */ CHECK(5, 11, strcmp(TEXT, text), 0, 0, "wave tx busy, serial read"); e = bb_serial_read_close(pi, GPIO); CHECK(5, 12, e, 0, 0, "serial read close"); c = wave_get_micros(pi); CHECK(5, 13, c, 6158148, 0, "wave get micros"); c = wave_get_high_micros(pi); if (c > 6158148) c = 6158148; CHECK(5, 14, c, 6158148, 0, "wave get high micros"); c = wave_get_max_micros(pi); CHECK(5, 15, c, 1800000000, 0, "wave get max micros"); c = wave_get_pulses(pi); CHECK(5, 16, c, 3405, 0, "wave get pulses"); c = wave_get_high_pulses(pi); CHECK(5, 17, c, 3405, 0, "wave get high pulses"); c = wave_get_max_pulses(pi); CHECK(5, 18, c, 12000, 0, "wave get max pulses"); c = wave_get_cbs(pi); if (c < 6963) CHECK(5, 19, c, 6810, 0, "wave get cbs"); else CHECK(5, 19, c, 7115, 0, "wave get cbs"); c = wave_get_high_cbs(pi); if (c < 6963) CHECK(5, 20, c, 6810, 0, "wave get high cbs"); else CHECK(5, 20, c, 7115, 0, "wave get high cbs"); c = wave_get_max_cbs(pi); CHECK(5, 21, c, 25016, 0, "wave get max cbs"); callback_cancel(id); } int t6_count=0; int t6_on=0; uint32_t t6_on_tick=0; void t6cbf(int pi, unsigned gpio, unsigned 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 pi) { int tp, t, p, id; printf("Trigger tests.\n"); gpio_write(pi, GPIO, PI_LOW); tp = 0; id = callback(pi, GPIO, EITHER_EDGE, t6cbf); time_sleep(0.2); for (t=0; t<5; t++) { time_sleep(0.1); p = 10 + (t*10); tp += p; gpio_trigger(pi, GPIO, p, 1); } time_sleep(0.5); CHECK(6, 1, t6_count, 5, 0, "gpio trigger count"); CHECK(6, 2, t6_on, tp, 25, "gpio trigger pulse length"); callback_cancel(id); } int t7_count=0; void t7cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) { if (level == PI_TIMEOUT) t7_count++; } void t7(int pi) { int c, oc, id; printf("Watchdog tests.\n"); /* type of edge shouldn't matter for watchdogs */ id = callback(pi, GPIO, FALLING_EDGE, t7cbf); set_watchdog(pi, GPIO, 50); /* 50 ms, 20 per second */ time_sleep(0.5); oc = t7_count; time_sleep(2); c = t7_count - oc; CHECK(7, 1, c, 39, 5, "set watchdog on count"); set_watchdog(pi, 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"); callback_cancel(id); } void t8(int pi) { int v; printf("Bank read/write tests.\n"); gpio_write(pi, GPIO, 0); v = read_bank_1(pi) & (1<<GPIO); CHECK(8, 1, v, 0, 0, "read bank 1"); gpio_write(pi, GPIO, 1); v = read_bank_1(pi) & (1<<GPIO); CHECK(8, 2, v, (1<<GPIO), 0, "read bank 1"); clear_bank_1(pi, 1<<GPIO); v = gpio_read(pi, GPIO); CHECK(8, 3, v, 0, 0, "clear bank 1"); set_bank_1(pi, 1<<GPIO); v = gpio_read(pi, GPIO); CHECK(8, 4, v, 1, 0, "set bank 1"); v = read_bank_2(pi); if (v) v = 0; else v = 1; CHECK(8, 5, v, 0, 0, "read bank 2"); v = clear_bank_2(pi, 0); CHECK(8, 6, v, 0, 0, "clear bank 2"); v = clear_bank_2(pi, 0xffffff); CHECK(8, 7, v, PI_SOME_PERMITTED, 0, "clear bank 2"); v = set_bank_2(pi, 0); CHECK(8, 8, v, 0, 0, "set bank 2"); v = set_bank_2(pi, 0xffffff); CHECK(8, 9, v, PI_SOME_PERMITTED, 0, "set bank 2"); } int t9_count = 0; void t9cbf(int pi, unsigned gpio, unsigned level, uint32_t tick) { t9_count++; } void t9(int pi) { int s, oc, c, e, id; uint32_t p[10]; printf("Script store/run/status/stop/delete tests.\n"); gpio_write(pi, GPIO, 0); /* need known state */ /* 100 loops per second p0 number of loops p1 GPIO */ char *script="\ ld p9 p0\ tag 0\ w p1 1\ mils 5\ w p1 0\ mils 5\ dcr p9\ jp 0"; id = callback(pi, GPIO, RISING_EDGE, t9cbf); s = store_script(pi, script); /* Wait for script to finish initing. */ while (1) { time_sleep(0.1); e = script_status(pi, s, p); if (e != PI_SCRIPT_INITING) break; } oc = t9_count; p[0] = 99; p[1] = GPIO; run_script(pi, s, 2, p); time_sleep(2); c = t9_count - oc; CHECK(9, 1, c, 100, 0, "store/run script"); oc = t9_count; p[0] = 200; p[1] = GPIO; run_script(pi, s, 2, p); while (1) { time_sleep(0.1); e = script_status(pi, s, p); if (e != PI_SCRIPT_RUNNING) break; } c = t9_count - oc; time_sleep(0.1); CHECK(9, 2, c, 201, 0, "run script/script status"); oc = t9_count; p[0] = 2000; p[1] = GPIO; run_script(pi, s, 2, p); while (1) { time_sleep(0.1); e = script_status(pi, s, p); if (e != PI_SCRIPT_RUNNING) break; if (p[9] < 1600) stop_script(pi, s); } c = t9_count - oc; time_sleep(0.1); CHECK(9, 3, c, 410, 10, "run/stop script/script status"); e = delete_script(pi, s); CHECK(9, 4, e, 0, 0, "delete script"); callback_cancel(id); } void ta(int pi) { int h, b, e; char *TEXT; char text[2048]; printf("Serial link tests.\n"); /* this test needs RXD and TXD to be connected */ h = serial_open(pi, "/dev/ttyAMA0", 57600, 0); CHECK(10, 1, h, 0, 0, "serial open"); time_sleep(0.1); /* allow time for transmission */ b = serial_read(pi, h, text, sizeof(text)); /* flush buffer */ b = serial_data_available(pi, h); CHECK(10, 2, b, 0, 0, "serial data available"); TEXT = "\ To be, or not to be, that is the question-\ Whether 'tis Nobler in the mind to suffer\ The Slings and Arrows of outrageous Fortune,\ Or to take Arms against a Sea of troubles,\ "; e = serial_write(pi, h, TEXT, strlen(TEXT)); CHECK(10, 3, e, 0, 0, "serial write"); e = serial_write_byte(pi, h, 0xAA); e = serial_write_byte(pi, h, 0x55); e = serial_write_byte(pi, h, 0x00); e = serial_write_byte(pi, h, 0xFF); CHECK(10, 4, e, 0, 0, "serial write byte"); time_sleep(0.1); /* allow time for transmission */ b = serial_data_available(pi, h); CHECK(10, 5, b, strlen(TEXT)+4, 0, "serial data available"); b = serial_read(pi, h, text, strlen(TEXT)); CHECK(10, 6, b, strlen(TEXT), 0, "serial read"); if (b >= 0) text[b] = 0; CHECK(10, 7, strcmp(TEXT, text), 0, 0, "serial read"); b = serial_read_byte(pi, h); CHECK(10, 8, b, 0xAA, 0, "serial read byte"); b = serial_read_byte(pi, h); CHECK(10, 9, b, 0x55, 0, "serial read byte"); b = serial_read_byte(pi, h); CHECK(10, 10, b, 0x00, 0, "serial read byte"); b = serial_read_byte(pi, h); CHECK(10, 11, b, 0xFF, 0, "serial read byte"); b = serial_data_available(pi, h); CHECK(10, 12, b, 0, 0, "serial data availabe"); e = serial_close(pi, h); CHECK(10, 13, e, 0, 0, "serial close"); } void tb(int pi) { 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 = i2c_open(pi, 1, 0x53, 0); CHECK(11, 1, h, 0, 0, "i2c open"); e = i2c_write_device(pi, h, "\x00", 1); /* move to known register */ CHECK(11, 2, e, 0, 0, "i2c write device"); b = i2c_read_device(pi, h, buf, 1); CHECK(11, 3, b, 1, 0, "i2c read device"); CHECK(11, 4, buf[0], 0xE5, 0, "i2c read device"); b = i2c_read_byte(pi, h); CHECK(11, 5, b, 0xE5, 0, "i2c read byte"); b = i2c_read_byte_data(pi, h, 0); CHECK(11, 6, b, 0xE5, 0, "i2c read byte data"); b = i2c_read_byte_data(pi, h, 48); CHECK(11, 7, b, 2, 0, "i2c read byte data"); exp = "\x1D[aBcDeFgHjKM]"; len = strlen(exp); e = i2c_write_device(pi, h, exp, len); CHECK(11, 8, e, 0, 0, "i2c write device"); e = i2c_write_device(pi, h, "\x1D", 1); b = i2c_read_device(pi, h, buf, len-1); CHECK(11, 9, b, len-1, 0, "i2c read device"); CHECK(11, 10, strncmp(buf, exp+1, len-1), 0, 0, "i2c read device"); if (strncmp(buf, exp+1, len-1)) printf("got [%.*s] expected [%.*s]\n", len-1, buf, len-1, exp+1); e = i2c_write_byte_data(pi, h, 0x1d, 0xAA); CHECK(11, 11, e, 0, 0, "i2c write byte data"); b = i2c_read_byte_data(pi, h, 0x1d); CHECK(11, 12, b, 0xAA, 0, "i2c read byte data"); e = i2c_write_byte_data(pi, h, 0x1d, 0x55); CHECK(11, 13, e, 0, 0, "i2c write byte data"); b = i2c_read_byte_data(pi, h, 0x1d); CHECK(11, 14, b, 0x55, 0, "i2c read byte data"); exp = "[1234567890#]"; len = strlen(exp); e = i2c_write_block_data(pi, h, 0x1C, exp, len); CHECK(11, 15, e, 0, 0, "i2c write block data"); e = i2c_write_device(pi, h, "\x1D", 1); b = i2c_read_device(pi, h, buf, len); CHECK(11, 16, b, len, 0, "i2c read device"); CHECK(11, 17, strncmp(buf, exp, len), 0, 0, "i2c read device"); if (strncmp(buf, exp, len)) printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); b = i2c_read_i2c_block_data(pi, h, 0x1D, buf, len); CHECK(11, 18, b, len, 0, "i2c read i2c block data"); CHECK(11, 19, strncmp(buf, exp, len), 0, 0, "i2c read i2c block data"); if (strncmp(buf, exp, len)) printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); exp = "(-+=;:,<>!%)"; len = strlen(exp); e = i2c_write_i2c_block_data(pi, h, 0x1D, exp, len); CHECK(11, 20, e, 0, 0, "i2c write i2c block data"); b = i2c_read_i2c_block_data(pi, h, 0x1D, buf, len); CHECK(11, 21, b, len, 0, "i2c read i2c block data"); CHECK(11, 22, strncmp(buf, exp, len), 0, 0, "i2c read i2c block data"); if (strncmp(buf, exp, len)) printf("got [%.*s] expected [%.*s]\n", len, buf, len, exp); e = i2c_close(pi, h); CHECK(11, 23, e, 0, 0, "i2c close"); } void tc(int pi) { int h, x, b, e; char buf[128]; printf("SPI tests."); /* this test requires a MCP3202 on SPI channel 1 */ h = spi_open(pi, 1, 50000, 0); CHECK(12, 1, h, 0, 0, "spi open"); for (x=0; x<5; x++) { sprintf(buf, "\x01\x80"); b = spi_xfer(pi, h, buf, buf, 3); CHECK(12, 2, b, 3, 0, "spi xfer"); if (b == 3) { time_sleep(1.0); printf("%d ", ((buf[1]&0x0F)*256)|buf[2]); } } e = spi_close(pi, h); CHECK(12, 99, e, 0, 0, "spi close"); } int main(int argc, char *argv[]) { int i, t, c, pi; char test[64]={0,}; if (argc > 1) { t = 0; for (i=0; i<strlen(argv[1]); i++) { c = tolower(argv[1][i]); if (!strchr(test, c)) { test[t++] = c; test[t] = 0; } } } else strcat(test, "0123456789"); pi = pigpio_start(0, 0); if (pi < 0) { fprintf(stderr, "pigpio initialisation failed (%d).\n", pi); return 1; } printf("Connected to pigpio daemon (%d).\n", pi); if (strchr(test, '0')) t0(pi); if (strchr(test, '1')) t1(pi); if (strchr(test, '2')) t2(pi); if (strchr(test, '3')) t3(pi); if (strchr(test, '4')) t4(pi); if (strchr(test, '5')) t5(pi); if (strchr(test, '6')) t6(pi); if (strchr(test, '7')) t7(pi); if (strchr(test, '8')) t8(pi); if (strchr(test, '9')) t9(pi); if (strchr(test, 'a')) ta(pi); if (strchr(test, 'b')) tb(pi); if (strchr(test, 'c')) tc(pi); pigpio_stop(pi); return 0; }