|
30 | 30 | #include <epicsAtomic.h> |
31 | 31 | #include <iocInit.h> |
32 | 32 | #include <initHooks.h> |
| 33 | +#include <longoutRecord.h> |
33 | 34 |
|
34 | 35 | #include <linux/gpio.h> |
35 | 36 | #include <fcntl.h> |
@@ -92,6 +93,7 @@ struct gpio_pin { |
92 | 93 | enum gpio_edge edge = GPIO_EDGE_RISING; |
93 | 94 | enum gpio_bias bias = GPIO_BIAS_NONE; |
94 | 95 | enum gpio_drive drive = GPIO_DRIVE_PUSH_PULL; |
| 96 | + uint32_t debounce_us = 0; /* debounce period, us */ |
95 | 97 | uint64_t ts; /* hardware/kernel timestamp */ |
96 | 98 | }; |
97 | 99 |
|
@@ -133,6 +135,16 @@ struct gpio_bo_cfg_dpvt { |
133 | 135 | gpio_bo_cfg_param param; |
134 | 136 | }; |
135 | 137 |
|
| 138 | +enum gpio_lo_cfg_param { |
| 139 | + GPIO_LO_CFG_DEBOUNCE, |
| 140 | +}; |
| 141 | + |
| 142 | +struct gpio_lo_cfg_dpvt { |
| 143 | + struct gpio_chip* chip; |
| 144 | + int pin; |
| 145 | + gpio_lo_cfg_param param; |
| 146 | +}; |
| 147 | + |
136 | 148 | static std::map<std::string, gpio_chip*> s_chips; |
137 | 149 |
|
138 | 150 | static void gpio_thread_proc(void* param); |
@@ -370,6 +382,12 @@ gpio_reconfig_pin(gpio_chip* chip, int pin) |
370 | 382 |
|
371 | 383 | config.num_attrs = 0; |
372 | 384 |
|
| 385 | + if (p.type == GPIO_TYPE_INPUT) { |
| 386 | + config.num_attrs = 1; |
| 387 | + config.attrs[0].attr.debounce_period_us = p.debounce_us; |
| 388 | + config.attrs[0].mask = 1<<p.num; |
| 389 | + } |
| 390 | + |
373 | 391 | if (ioctl(p.fd, GPIO_V2_LINE_SET_CONFIG_IOCTL, &config) < 0) { |
374 | 392 | perror("ioctl(GPIO_V2_LINE_SET_CONFIG_IOCTL)"); |
375 | 393 | return false; |
@@ -716,6 +734,77 @@ devGpioCfgMbbo_WriteRecord(mbboRecord* precord) |
716 | 734 | return 0; |
717 | 735 | } |
718 | 736 |
|
| 737 | +/**************************** devGpioCfgLo *****************************/ |
| 738 | + |
| 739 | +static long devGpioCfgLo_InitRecord(dbCommon* precord); |
| 740 | +static long devGpioCfgLo_WriteRecord(longoutRecord* precord); |
| 741 | + |
| 742 | +longoutdset devGpioCfgLo = { |
| 743 | + .common = { |
| 744 | + .number = 5, |
| 745 | + .init_record = devGpioCfgLo_InitRecord, |
| 746 | + }, |
| 747 | + .write_longout = devGpioCfgLo_WriteRecord |
| 748 | +}; |
| 749 | + |
| 750 | +static bool |
| 751 | +devGpioCfgLo_ParseInstio(gpio_lo_cfg_dpvt* dpvt, char* rem) |
| 752 | +{ |
| 753 | + char* param = strtok(rem, ","); |
| 754 | + if (!param) { |
| 755 | + printf("%s: Bad param type\n", __func__); |
| 756 | + return false; |
| 757 | + } |
| 758 | + |
| 759 | + if (!strcmp(param, "debounce")) |
| 760 | + dpvt->param = GPIO_LO_CFG_DEBOUNCE; |
| 761 | + else { |
| 762 | + printf("%s: Bad cfg param\n", __func__); |
| 763 | + return false; |
| 764 | + } |
| 765 | + return true; |
| 766 | +} |
| 767 | + |
| 768 | +static long |
| 769 | +devGpioCfgLo_InitRecord(dbCommon* precord) |
| 770 | +{ |
| 771 | + auto* plo = reinterpret_cast<longoutRecord*>(precord); |
| 772 | + auto* dpvt = dpvt_create<gpio_lo_cfg_dpvt>(plo->out.value.instio.string, devGpioCfgLo_ParseInstio); |
| 773 | + |
| 774 | + if (!dpvt) |
| 775 | + return S_dev_badOutType; |
| 776 | + |
| 777 | + plo->dpvt = dpvt; |
| 778 | + return 0; |
| 779 | +} |
| 780 | + |
| 781 | +static long |
| 782 | +devGpioCfgLo_WriteRecord(longoutRecord* precord) |
| 783 | +{ |
| 784 | + auto* dpvt = dpvt_get<gpio_lo_cfg_dpvt>(precord); |
| 785 | + if (!dpvt) |
| 786 | + return 1; |
| 787 | + |
| 788 | + auto& p = dpvt->chip->pins[dpvt->pin]; |
| 789 | + |
| 790 | + switch (dpvt->param) { |
| 791 | + case GPIO_LO_CFG_DEBOUNCE: |
| 792 | + p.debounce_us = precord->val; |
| 793 | + break; |
| 794 | + default: |
| 795 | + assert(0); |
| 796 | + } |
| 797 | + |
| 798 | + if (!gpio_reconfig_pin(dpvt->chip, dpvt->pin)) { |
| 799 | + recGblSetSevr(precord, COMM_ALARM, MAJOR_ALARM); |
| 800 | + return 1; |
| 801 | + } |
| 802 | + |
| 803 | + return 0; |
| 804 | +} |
| 805 | + |
| 806 | +epicsExportAddress(dset, devGpioCfgLo); |
| 807 | + |
719 | 808 | /**************************** Input Event Thread *****************************/ |
720 | 809 |
|
721 | 810 | /* NOTE: This code assumes that we have one fd per pin. */ |
|
0 commit comments