void generateIOComponentModules() { std::list<Output *> output_list; { boost::mutex::scoped_lock lock(thread_protection_mutex); int remaining = machines.size(); std::cout << remaining << " Machines\n"; std::cout << "Linking clockwork machines to hardware\n"; std::map<std::string, MachineInstance*>::const_iterator iter = machines.begin(); while (iter != machines.end()) { const int error_buf_size = 100; char error_buf[error_buf_size]; MachineInstance *m = (*iter).second; iter++; --remaining; if ( (m->_type == "POINT" || m->_type == "ANALOGINPUT" || m->_type == "COUNTERRATE" || m->_type == "COUNTER" || m->_type == "STATUS_FLAG" || m->_type == "ANALOGOUTPUT" ) && m->parameters.size() > 1) { output_points.push_back(m); // points should have two parameters, the name of the io module and the bit offset //Parameter module = m->parameters[0]; //Parameter offset = m->parameters[1]; //Value params = p.val; //if (params.kind == Value::t_list && params.listValue.size() > 1) { std::string name; unsigned int entry_position = 0; if (m->_type == "COUNTERRATE") { name = m->parameters[1].real_name; entry_position = m->parameters[2].val.iValue; } else { name = m->parameters[0].real_name; entry_position = m->parameters[1].val.iValue; } #if 0 std::cerr << "Setting up point " << m->getName() << " " << entry_position << " on module " << name << "\n"; #endif MachineInstance *module_mi = MachineInstance::find(name.c_str()); if (!module_mi) { snprintf(error_buf, error_buf_size, "No machine called %s", name.c_str()); MessageLog::instance()->add(error_buf); std::cerr << error_buf << "\n"; error_messages.push_back(error_buf); ++num_errors; continue; } if (!module_mi->properties.exists("position")) // module position not given { snprintf(error_buf, error_buf_size, "Machine %s does not specify a position", module_mi->getName().c_str()); MessageLog::instance()->add(error_buf); std::cerr << error_buf << "\n"; error_messages.push_back(error_buf); ++num_errors; continue; } if (m->_type == "ANALOGOUTPUT") { const Value &default_value = m->properties.lookup("default"); if (default_value == SymbolTable::Null) { snprintf(error_buf, error_buf_size, "Machine %s must specify a default value", m->getName().c_str()); MessageLog::instance()->add(error_buf); std::cerr << error_buf << "\n"; error_messages.push_back(error_buf); ++num_errors; } } int module_position = module_mi->properties.lookup("position").iValue; if (module_position == -1) // module position unmapped { snprintf(error_buf, error_buf_size, "Machine %s position not mapped", name.c_str()); MessageLog::instance()->add(error_buf); std::cerr << error_buf << "\n"; continue; } #ifndef EC_SIMULATOR // some modules have multiple io types (eg the EK1814) and therefore // multiple syncmasters, we number // the points from 1..n but the device numbers them 1.n,1.m,..., resetting // the index for each sync master. ECModule *module = ECInterface::findModule(module_position); if (!module) { snprintf(error_buf, error_buf_size, "No module found at position %d for %s", module_position, m->getName().c_str()); MessageLog::instance()->add(error_buf); std::cerr << error_buf << "\n"; error_messages.push_back(error_buf); ++num_errors; continue; } if (entry_position >= module->num_entries) { snprintf(error_buf, error_buf_size, "No entry %d on module %d (%s)", entry_position, module_position, name.c_str()); MessageLog::instance()->add(error_buf); std::cerr << error_buf << "\n"; error_messages.push_back(error_buf); ++num_errors; continue; // could not find this device } EntryDetails *ed = &module->entry_details[entry_position]; unsigned int direction = module->syncs[ed->sm_index].dir; unsigned int offset_idx = entry_position; unsigned int bitlen = module->pdo_entries[entry_position].bit_length; if (direction == EC_DIR_OUTPUT) { #if 0 std::cerr << "Adding new output device " << m->getName() << " position: " << entry_position << " name: " << module->entry_details[offset_idx].name << " bit_pos: " << module->bit_positions[offset_idx] << " offset: " << module->offsets[offset_idx] << " bitlen: " << bitlen << "\n"; #endif IOAddress addr ( IOComponent::add_io_entry(ed->name.c_str(), module_position, module->offsets[offset_idx], module->bit_positions[offset_idx], offset_idx, bitlen)); if (bitlen == 1) { Output *o = new Output(addr); output_list.push_back(o); IOComponent::devices[m->getName().c_str()] = o; o->setName(m->getName().c_str()); m->io_interface = o; o->addDependent(m); o->addOwner(m); } else { AnalogueOutput *o = new AnalogueOutput(addr); output_list.push_back(o); IOComponent::devices[m->getName().c_str()] = o; o->setName(m->getName().c_str()); m->io_interface = o; o->addDependent(m); o->addOwner(m); o->setupProperties(m); } } else { //sstr << m->getName() << "_IN_" << entry_position << std::flush; //const char *name_str = sstr.str().c_str(); #if 1 std::cerr << "Adding new input device " << m->getName() << " position: " << entry_position << " name: " << module->entry_details[offset_idx].name << " sm_idx: " << std::hex << ed->sm_index << std::dec << " bit_pos: " << module->bit_positions[offset_idx] << " offset: " << module->offsets[offset_idx] << " bitlen: " << bitlen << "\n"; #endif IOAddress addr( IOComponent::add_io_entry(ed->name.c_str(), module_position, module->offsets[offset_idx], module->bit_positions[offset_idx], offset_idx, bitlen)); if (bitlen == 1) { Input *in = new Input(addr); IOComponent::devices[m->getName().c_str()] = in; in->setName(m->getName().c_str()); m->io_interface = in; in->addDependent(m); in->addOwner(m); } else { if (m->_type == "COUNTERRATE") { CounterRate *in = new CounterRate(addr); char *nm = strdup(m->getName().c_str()); IOComponent::devices[nm] = in; free(nm); in->setName(m->getName().c_str()); m->io_interface = in; in->addDependent(m); in->addOwner(m); m->setNeedsThrottle(true); in->setupProperties(m); } else if (m->_type == "COUNTER") { Counter *in = new Counter(addr); char *nm = strdup(m->getName().c_str()); IOComponent::devices[nm] = in; free(nm); in->setName(m->getName().c_str()); m->io_interface = in; in->addDependent(m); in->addOwner(m); in->setupProperties(m); m->setNeedsThrottle(true); } else { AnalogueInput *in = new AnalogueInput(addr); char *nm = strdup(m->getName().c_str()); IOComponent::devices[nm] = in; free(nm); in->setName(m->getName().c_str()); m->io_interface = in; in->addDependent(m); in->addOwner(m); in->setupProperties(m); m->setNeedsThrottle(true); } } } #endif } else { #if 0 if (m->_type != "POINT" && m->_type != "STATUS_FLAG" && m->_type != "COUNTERRATE" && m->_type != "COUNTER" && m->_type != "ANALOGINPUT" && m->_type != "ANALOGOUTPUT" ) DBG_MSG << "Skipping " << m->_type << " " << m->getName() << " (not a POINT)\n"; else DBG_MSG << "Skipping " << m->_type << " " << m->getName() << " (no parameters)\n"; #endif } } assert(remaining==0); } }