#include "rtapi_ctype.h"
#include "rtapi.h"
#include "rtapi_app.h"
#include "hal.h"
#define MAX_GROUP 8
#define STRINGIZE(x) #x
#define MAX_GROUP_STR STRINGIZE(MAX_GROUP)
MODULE_AUTHOR("John Kasunich");
MODULE_DESCRIPTION("Debounce filter for EMC HAL");
MODULE_LICENSE("GPL");
int cfg[MAX_GROUP] = {0,};
RTAPI_MP_ARRAY_INT(cfg,MAX_GROUP,"Group size for up to "MAX_GROUP_STR" groups");
typedef struct {
hal_bit_t *in;
hal_bit_t *out;
hal_s32_t state;
} debounce_t;
typedef struct {
int channels;
hal_s32_t delay;
debounce_t *filter_array;
} debounce_group_t;
static debounce_group_t *group_array;
static int comp_id;
static int num_groups;
static int num_filters;
static int export_filter(int num, debounce_t * addr, int group_num);
static int export_group(int num, debounce_group_t * addr, int group_size);
static void debounce(void *arg, long period);
#define MAX_GROUP_SIZE 50
int rtapi_app_main(void)
{
int retval, n;
num_groups = 0;
num_filters = 0;
while ((num_groups < MAX_GROUP) && (cfg[num_groups] != 0)) {
if ((cfg[num_groups] < 1)
|| (cfg[num_groups] > MAX_GROUP_SIZE)) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: bad group size '%d'\n", cfg[num_groups]);
return -1;
}
num_filters += cfg[num_groups];
num_groups++;
}
if (num_groups == 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: no channels configured\n");
return -1;
}
comp_id = hal_init("debounce");
if (comp_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: hal_init() failed\n");
return -1;
}
group_array = hal_malloc(num_groups * sizeof(debounce_group_t));
if (group_array == 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: hal_malloc() failed\n");
hal_exit(comp_id);
return -1;
}
for (n = 0; n < num_groups; n++) {
retval = export_group(n, &(group_array[n]), cfg[n]);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: group %d export failed\n", n);
hal_exit(comp_id);
return -1;
}
}
rtapi_print_msg(RTAPI_MSG_INFO,
"DEBOUNCE: installed %d groups of debounce filters, %d total\n",
num_groups, num_filters);
hal_ready(comp_id);
return 0;
}
void rtapi_app_exit(void)
{
hal_exit(comp_id);
}
static void debounce(void *arg, long period)
{
debounce_group_t *group;
debounce_t *filter;
int n;
group = (debounce_group_t *) arg;
if (group->delay < 0) {
group->delay = 1;
}
for (n = 0; n < group->channels; n++) {
filter = &(group->filter_array[n]);
if (*(filter->in)) {
if (filter->state < group->delay) {
filter->state++;
} else {
*(filter->out) = 1;
}
} else {
if (filter->state > 0) {
filter->state--;
} else {
*(filter->out) = 0;
}
}
}
}
static int export_group(int num, debounce_group_t * addr, int group_size)
{
int n, retval, msg;
char buf[HAL_NAME_LEN + 1];
msg = rtapi_get_msg_level();
rtapi_set_msg_level(RTAPI_MSG_WARN);
addr->filter_array = hal_malloc(group_size * sizeof(debounce_t));
if (addr->filter_array == 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: hal_malloc() failed\n");
return -1;
}
rtapi_snprintf(buf, sizeof(buf), "debounce.%d.delay", num);
retval = hal_param_s32_new(buf, HAL_RW, &(addr->delay), comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: '%s' param export failed\n", buf);
return retval;
}
rtapi_snprintf(buf, sizeof(buf), "debounce.%d", num);
retval = hal_export_funct(buf, debounce, addr, 0, 0, comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: '%s' funct export failed\n", buf);
return -1;
}
addr->delay = 5;
addr->channels = group_size;
for (n = 0; n < group_size; n++) {
retval = export_filter(n, &(addr->filter_array[n]), num);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: filter %d export failed\n", n);
return -1;
}
}
rtapi_set_msg_level(msg);
return 0;
}
static int export_filter(int num, debounce_t * addr, int group_num)
{
int retval;
char buf[HAL_NAME_LEN + 1];
rtapi_snprintf(buf, sizeof(buf), "debounce.%d.%d.in", group_num, num);
retval = hal_pin_bit_new(buf, HAL_IN, &(addr->in), comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: '%s' pin export failed\n", buf);
return retval;
}
rtapi_snprintf(buf, sizeof(buf), "debounce.%d.%d.out", group_num, num);
retval = hal_pin_bit_new(buf, HAL_OUT, &(addr->out), comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: '%s' pin export failed\n", buf);
return retval;
}
#ifdef EXPORT_STATE
rtapi_snprintf(buf, sizeof(buf), "debounce.%d.%d.state", group_num, num);
retval = hal_param_s32_new(buf, HAL_RO, &(addr->state), comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"DEBOUNCE: ERROR: '%s' param export failed\n", buf);
return retval;
}
#endif
addr->state = 0;
*(addr->out) = 0;
return 0;
}