#include "ModelEditor.h" uint8_t firstFreeId(const uint8_t *usedIds, size_t count, uint8_t lastId) { for(uint16_t id = 1; id <= lastId; id++) { bool used = false; for(size_t i = 0; i < count && !used; i++) used = usedIds[i] == id; if(!used) return static_cast(id); } return 0; } int8_t nextSortOrder(const int8_t *orders, size_t count) { int8_t order = -1; for(size_t i = 0; i < count; i++) if(orders[i] > order) order = orders[i]; return order + 1; } uint32_t freeRemoteAddress(uint32_t candidate, const uint32_t *used, size_t count) { // Start over after every bump: the new address may be taken too. for(size_t i = 0; i < count; i++) { if(used[i] == candidate) { candidate++; i = static_cast(-1); } } return candidate; } template static bool addTo(T *list, size_t size, T item) { for(size_t i = 0; i < size; i++) if(list[i] == item) return true; for(size_t i = 0; i < size; i++) { if(list[i] == 0) { list[i] = item; return true; } } return false; } template static bool removeFrom(T *list, size_t size, T item) { bool removed = false; size_t j = 0; for(size_t i = 0; i < size; i++) { if(list[i] == 0) continue; if(list[i] == item) removed = true; else list[j++] = list[i]; } while(j < size) list[j++] = 0; return removed; } void packList(uint8_t *list, size_t size) { removeFrom(list, size, 0); } bool addToList(uint8_t *list, size_t size, uint8_t item) { return addTo(list, size, item); } bool addToList(uint32_t *list, size_t size, uint32_t item) { return addTo(list, size, item); } bool removeFromList(uint8_t *list, size_t size, uint8_t item) { return removeFrom(list, size, item); } bool removeFromList(uint32_t *list, size_t size, uint32_t item) { return removeFrom(list, size, item); } int8_t gpioPinConflict(shade_types type, radio_proto proto, uint8_t upPin, uint8_t downPin, uint8_t myPin, const pin_users_t &radio, const pin_users_t ðernet, const pin_users_t &otherShades) { if(proto != radio_proto::GP_Relay && proto != radio_proto::GP_Remote) return 0; // A dry contact or a single button gate driven by a remote only uses the down // pin; a two way dry contact and a relay don't use My. if(type == shade_types::drycontact || ((type == shade_types::garage1 || type == shade_types::lgate1 || type == shade_types::cgate1 || type == shade_types::rgate1) && proto == radio_proto::GP_Remote)) upPin = myPin = 255; else if(type == shade_types::drycontact2) myPin = 255; if(proto == radio_proto::GP_Relay) myPin = 255; const uint8_t pins[] = { upPin, downPin, myPin }; auto clash = [&pins](const pin_users_t &users) { for(uint8_t pin : pins) if(pin != 255 && users.usesPin(pin)) return true; return false; }; if(clash(radio)) return PIN_CONFLICT_RADIO; if(clash(ethernet)) return PIN_CONFLICT_ETHERNET; if(clash(otherShades)) return PIN_CONFLICT_SHADE; return 0; }