// // Copyright (C) 2007-2008 Sebastian Kuzminsky // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #include #include "rtapi.h" #include "rtapi_string.h" #include "rtapi_math.h" #include "hal.h" #include "hal/drivers/mesa-hostmot2/hostmot2.h" void hm2_oneshot_update_width1(hostmot2_t *hm2, int i) { // widths are in ms hm2->oneshot.width1_reg[i] = (double)*hm2->oneshot.instance[i].hal.pin.width1 * ((double)hm2->oneshot.clock_frequency / (double)1e3); if (hm2->oneshot.width1_reg[i] > 0x7FFFFFFF) { HM2_ERR("oneshot %d has invalid width1, resetting to max\n", i); hm2->oneshot.width1_reg[i] = 0x7FFFFFFF; *hm2->oneshot.instance[i].hal.pin.width1 = (double)hm2->oneshot.width1_reg[i] * ((double)1e3 / (double)hm2->oneshot.clock_frequency); } } void hm2_oneshot_update_width2(hostmot2_t *hm2, int i) { // widths are in ms hm2->oneshot.width2_reg[i] = (double)*hm2->oneshot.instance[i].hal.pin.width2 * ((double)hm2->oneshot.clock_frequency / (double)1e3); if (hm2->oneshot.width2_reg[i] > 0x7FFFFFFF) { HM2_ERR("oneshot %d has invalid width1, resetting to max\n", i); hm2->oneshot.width2_reg[i] = 0x7FFFFFFF; *hm2->oneshot.instance[i].hal.pin.width2 = (double)hm2->oneshot.width2_reg[i] * ((double)1e3 / (double)hm2->oneshot.clock_frequency); } } void hm2_oneshot_update_filter1(hostmot2_t *hm2, int i) { // widths are in ms hm2->oneshot.filter1_reg[i] = (double)*hm2->oneshot.instance[i].hal.pin.filter1 * ((double)hm2->oneshot.clock_frequency / (double)1e3); if (hm2->oneshot.filter1_reg[i] > 0xFFFFFF) { HM2_ERR("oneshot %d has invalid filter1 time, resetting to max\n", i); hm2->oneshot.width1_reg[i] = 0xFFFFFF; *hm2->oneshot.instance[i].hal.pin.filter1 = (double)hm2->oneshot.filter1_reg[i] * ((double)1e3 / (double)hm2->oneshot.clock_frequency); } } void hm2_oneshot_update_filter2(hostmot2_t *hm2, int i) { // widths are in ms hm2->oneshot.filter2_reg[i] = (double)*hm2->oneshot.instance[i].hal.pin.filter2 * ((double)hm2->oneshot.clock_frequency / (double)1e3); if (hm2->oneshot.filter2_reg[i] > 0xFFFFFF) { HM2_ERR("oneshot %d has invalid filter2 time, resetting to max\n", i); hm2->oneshot.width2_reg[i] = 0xFFFFFF; *hm2->oneshot.instance[i].hal.pin.filter2 = (double)hm2->oneshot.filter2_reg[i] * ((double)1e3 / (double)hm2->oneshot.clock_frequency); } } void hm2_oneshot_update_rate(hostmot2_t *hm2, int i) { hm2->oneshot.rate_reg[i] = (uint32_t)(*hm2->oneshot.instance[i].hal.pin.rate * (4294967296.0 / (double)hm2->oneshot.clock_frequency)); } void hm2_oneshot_update_control(hostmot2_t *hm2, int i) { rtapi_u32 controlbuff; if(*hm2->oneshot.instance[i].hal.pin.trigselect1 > 7) { HM2_ERR("oneshot %d has invalid trigger 1 select value , resetting to 0\n", i); *hm2->oneshot.instance[i].hal.pin.trigselect1 = 0; } if(*hm2->oneshot.instance[i].hal.pin.trigselect2 > 7) { HM2_ERR("oneshot %d has invalid trigger 2 select value , resetting to 0\n", i); *hm2->oneshot.instance[i].hal.pin.trigselect2 = 0; } controlbuff = 0; controlbuff |= (*hm2->oneshot.instance[i].hal.pin.trigselect1 << 0); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.trigrise1 << 3); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.trigfall1 << 4); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.retrig1 << 5); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.enable1 << 6); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.reset1 << 7); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.swtrig1 << 10); controlbuff |= ((*hm2->oneshot.instance[i].hal.pin.dpll_timer_num & 7) << 12); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.trigselect2 << 16); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.trigrise2 << 19); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.trigfall2 << 20); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.retrig2 << 21); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.enable2 << 22); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.reset2 << 23); controlbuff |= (*hm2->oneshot.instance[i].hal.pin.swtrig2 << 26); hm2->oneshot.control_reg[i] = controlbuff; } void hm2_oneshot_update_regs(hostmot2_t *hm2) { int i; if (hm2->oneshot.num_instances == 0) return; for (i = 0; i < hm2->oneshot.num_instances; i ++) { hm2_oneshot_update_width1(hm2,i); hm2_oneshot_update_width2(hm2,i); hm2_oneshot_update_filter1(hm2,i); hm2_oneshot_update_filter2(hm2,i); hm2_oneshot_update_rate(hm2,i); hm2_oneshot_update_control(hm2,i); } } void hm2_oneshot_force_write(hostmot2_t *hm2) { hm2_oneshot_update_regs(hm2); hm2->llio->write(hm2->llio, hm2->oneshot.width1_addr, hm2->oneshot.width1_reg, (hm2->oneshot.num_instances * sizeof(rtapi_u32))); hm2->llio->write(hm2->llio, hm2->oneshot.width2_addr, hm2->oneshot.width2_reg, (hm2->oneshot.num_instances * sizeof(rtapi_u32))); hm2->llio->write(hm2->llio, hm2->oneshot.filter1_addr, hm2->oneshot.filter1_reg, (hm2->oneshot.num_instances * sizeof(rtapi_u32))); hm2->llio->write(hm2->llio, hm2->oneshot.filter2_addr, hm2->oneshot.filter2_reg, (hm2->oneshot.num_instances * sizeof(rtapi_u32))); hm2->llio->write(hm2->llio, hm2->oneshot.rate_addr, hm2->oneshot.rate_reg, (hm2->oneshot.num_instances * sizeof(rtapi_u32))); hm2->llio->write(hm2->llio, hm2->oneshot.control_addr, hm2->oneshot.control_reg, (hm2->oneshot.num_instances * sizeof(rtapi_u32))); if ((*hm2->llio->io_error) != 0) return; } // // Since these are all pins, write is the same as force write // void hm2_oneshot_write(hostmot2_t *hm2) { if (hm2->oneshot.num_instances == 0) return; hm2_oneshot_force_write(hm2); } int hm2_oneshot_parse_md(hostmot2_t *hm2, int md_index) { hm2_module_descriptor_t *md = &hm2->md[md_index]; int r; // // some standard sanity checks // if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 6, 4, 0x003F)) { HM2_ERR("inconsistent Module Descriptor!\n"); return -EINVAL; } if (hm2->oneshot.num_instances != 0) { HM2_ERR( "found duplicate Module Descriptor for %s (inconsistent firmware), not loading driver\n", hm2_get_general_function_name(md->gtag) ); return -EINVAL; } if (hm2->config.num_oneshots > md->instances) { HM2_ERR( "config.num_oneshots=%d, but only %d are available, not loading driver\n", hm2->config.num_oneshots, md->instances ); return -EINVAL; } if (hm2->config.num_oneshots == 0) { return 0; } // // looks good, start initializing // if (hm2->config.num_oneshots == -1) { hm2->oneshot.num_instances = md->instances; } else { hm2->oneshot.num_instances = hm2->config.num_oneshots; } hm2->oneshot.instance = (hm2_oneshot_instance_t *)hal_malloc(hm2->oneshot.num_instances * sizeof(hm2_oneshot_instance_t)); if (hm2->oneshot.instance == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail0; } hm2->oneshot.clock_frequency = md->clock_freq; hm2->oneshot.version = md->version; hm2->oneshot.width1_addr = md->base_address + (0 * md->register_stride); hm2->oneshot.width2_addr = md->base_address + (1 * md->register_stride); hm2->oneshot.filter1_addr = md->base_address + (2 * md->register_stride); hm2->oneshot.filter2_addr = md->base_address + (3 * md->register_stride); hm2->oneshot.rate_addr = md->base_address + (4 * md->register_stride); hm2->oneshot.control_addr = md->base_address + (5 * md->register_stride); hm2->oneshot.control_read_addr = md->base_address + (5 * md->register_stride); r = hm2_register_tram_write_region(hm2, hm2->oneshot.width1_addr, (hm2->oneshot.num_instances * sizeof(rtapi_u32)), &hm2->oneshot.width1_reg); if (r < 0) { HM2_ERR("error registering tram write region for Width1 register (%d)\n", r); goto fail0; } r = hm2_register_tram_write_region(hm2, hm2->oneshot.width2_addr, (hm2->oneshot.num_instances * sizeof(rtapi_u32)), &hm2->oneshot.width2_reg); if (r < 0) { HM2_ERR("error registering tram write region for Width2 register (%d)\n", r); goto fail0; } r = hm2_register_tram_write_region(hm2, hm2->oneshot.filter1_addr, (hm2->oneshot.num_instances * sizeof(rtapi_u32)), &hm2->oneshot.filter1_reg); if (r < 0) { HM2_ERR("error registering tram write region for Filter1 register (%d)\n", r); goto fail0; } r = hm2_register_tram_write_region(hm2, hm2->oneshot.filter2_addr, (hm2->oneshot.num_instances * sizeof(rtapi_u32)), &hm2->oneshot.filter2_reg); if (r < 0) { HM2_ERR("error registering tram write region for Filter2 register (%d)\n", r); goto fail0; } r = hm2_register_tram_write_region(hm2, hm2->oneshot.rate_addr, (hm2->oneshot.num_instances * sizeof(rtapi_u32)), &hm2->oneshot.rate_reg); if (r < 0) { HM2_ERR("error registering tram write region for Rate register (%d)\n", r); goto fail0; } r = hm2_register_tram_write_region(hm2, hm2->oneshot.control_addr, (hm2->oneshot.num_instances * sizeof(rtapi_u32)), &hm2->oneshot.control_reg); if (r < 0) { HM2_ERR("error registering tram write region for Control register (%d)\n", r); goto fail0; } r = hm2_register_tram_read_region(hm2, hm2->oneshot.control_read_addr, (hm2->oneshot.num_instances * sizeof(rtapi_u32)), &hm2->oneshot.control_read_reg); if (r < 0) { HM2_ERR("error registering tram read region for Control register (%d)\n", r); goto fail0; } // export to HAL // FIXME: r hides the r in enclosing function, and it returns the wrong thing { int i; int r; char name[HAL_NAME_LEN + 1]; for (i = 0; i < hm2->oneshot.num_instances; i ++) { // pins rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.width1", hm2->llio->name, i); r = hal_pin_float_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.width1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.width2", hm2->llio->name, i); r = hal_pin_float_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.width2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.filter1", hm2->llio->name, i); r = hal_pin_float_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.filter1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.filter2", hm2->llio->name, i); r = hal_pin_float_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.filter2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.rate", hm2->llio->name, i); r = hal_pin_float_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.rate), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.trigger_select1", hm2->llio->name, i); r = hal_pin_u32_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.trigselect1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.trigger_select2", hm2->llio->name, i); r = hal_pin_u32_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.trigselect2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.dpll_timer_number", hm2->llio->name, i); r = hal_pin_s32_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.dpll_timer_num), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.trigger_on_rise1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.trigrise1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.trigger_on_rise2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.trigrise2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.trigger_on_fall1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.trigfall1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.trigger_on_fall2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.trigfall2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.retriggerable1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.retrig1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.retriggerable2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.retrig2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.enable1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.enable1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.enable2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.enable2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.reset1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.reset1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.reset2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.reset2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.swtrigger1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.swtrig1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.swtrigger2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_IN, &(hm2->oneshot.instance[i].hal.pin.swtrig2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.exttrigger1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_OUT, &(hm2->oneshot.instance[i].hal.pin.exttrig1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.exttrigger2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_OUT, &(hm2->oneshot.instance[i].hal.pin.exttrig2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.out1", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_OUT, &(hm2->oneshot.instance[i].hal.pin.out1), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } rtapi_snprintf(name, sizeof(name), "%s.oneshot.%02d.out2", hm2->llio->name, i); r = hal_pin_bit_new(name, HAL_OUT, &(hm2->oneshot.instance[i].hal.pin.out2), hm2->llio->comp_id); if (r < 0) { HM2_ERR("error adding pin '%s', aborting\n", name); goto fail1; } // init hal objects *(hm2->oneshot.instance[i].hal.pin.width1) = 1.0; *(hm2->oneshot.instance[i].hal.pin.width2) = 1.0; *(hm2->oneshot.instance[i].hal.pin.filter1) = 0.1; *(hm2->oneshot.instance[i].hal.pin.filter2) = 0.1; *(hm2->oneshot.instance[i].hal.pin.rate) = 1000.0; *(hm2->oneshot.instance[i].hal.pin.trigselect1) = 0; *(hm2->oneshot.instance[i].hal.pin.trigselect2) = 0; *(hm2->oneshot.instance[i].hal.pin.trigrise1) = 0; *(hm2->oneshot.instance[i].hal.pin.trigrise2) = 0; *(hm2->oneshot.instance[i].hal.pin.trigfall1) = 0; *(hm2->oneshot.instance[i].hal.pin.trigfall2) = 0; *(hm2->oneshot.instance[i].hal.pin.retrig1) = 0; *(hm2->oneshot.instance[i].hal.pin.retrig2) = 0; *(hm2->oneshot.instance[i].hal.pin.enable1) = 0; *(hm2->oneshot.instance[i].hal.pin.enable2) = 0; *(hm2->oneshot.instance[i].hal.pin.reset1) = 0; *(hm2->oneshot.instance[i].hal.pin.reset2) = 0; *(hm2->oneshot.instance[i].hal.pin.swtrig1) = 0; *(hm2->oneshot.instance[i].hal.pin.swtrig2) = 0; } } return hm2->oneshot.num_instances; fail1: rtapi_kfree(hm2->oneshot.control_reg); fail0: hm2->oneshot.num_instances = 0; return r; } void hm2_oneshot_cleanup(hostmot2_t *hm2) { if (hm2->oneshot.num_instances <= 0) return; if (hm2->oneshot.control_reg != NULL) { rtapi_kfree(hm2->oneshot.control_reg); hm2->oneshot.control_reg = NULL; } hm2->oneshot.num_instances = 0; } void hm2_oneshot_print_module(hostmot2_t *hm2) { int i; if (hm2->oneshot.num_instances <= 0) return; HM2_PRINT("OneShots: %d\n", hm2->oneshot.num_instances); HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n", hm2->oneshot.clock_frequency, hm2_hz_to_mhz(hm2->oneshot.clock_frequency)); HM2_PRINT(" version: %d\n", hm2->oneshot.version); HM2_PRINT(" width1_addr: 0x%04X\n", hm2->oneshot.width1_addr); HM2_PRINT(" width2_addr: 0x%04X\n", hm2->oneshot.width2_addr); HM2_PRINT(" filter1_addr: 0x%04X\n", hm2->oneshot.filter1_addr); HM2_PRINT(" filter2_addr: 0x%04X\n", hm2->oneshot.filter2_addr); HM2_PRINT(" rate_addr: 0x%04X\n", hm2->oneshot.rate_addr); HM2_PRINT(" control_addr: 0x%04X\n", hm2->oneshot.control_addr); for (i = 0; i < hm2->oneshot.num_instances; i ++) { HM2_PRINT(" width1_reg = 0x%08X\n", hm2->oneshot.width1_reg[i]); HM2_PRINT(" width2_reg = 0x%08X\n", hm2->oneshot.width2_reg[i]); HM2_PRINT(" filter1_reg = 0x%08X\n", hm2->oneshot.filter1_reg[i]); HM2_PRINT(" filter2_reg = 0x%08X\n", hm2->oneshot.filter2_reg[i]); HM2_PRINT(" rate_reg = 0x%08X\n", hm2->oneshot.rate_reg[i]); HM2_PRINT(" control_reg = 0x%08X\n", hm2->oneshot.control_reg[i]); } } void hm2_oneshot_prepare_tram_write(hostmot2_t *hm2) { if (hm2->oneshot.num_instances <= 0) return; hm2_oneshot_update_regs(hm2); } void hm2_oneshot_process_tram_read(hostmot2_t *hm2) { int i; rtapi_u32 control = 0; for (i = 0; i < hm2->oneshot.num_instances; i ++) { control = hm2->oneshot.control_read_reg[i]; *hm2->oneshot.instance[i].hal.pin.out1 = ((control & (1 << 8)) != 0); *hm2->oneshot.instance[i].hal.pin.out2 = ((control & (1 << 24)) != 0); *hm2->oneshot.instance[i].hal.pin.exttrig1 = ((control & (1 << 9)) != 0); *hm2->oneshot.instance[i].hal.pin.exttrig2 = ((control & (1 << 25)) != 0); } }