[{"data":1,"prerenderedAt":1316},["ShallowReactive",2],{"manifest":3,"hreflang-alternates":990,"doc-pl-bloki-logiczne\u002Fprocess\u002Fgate":993},{"site":4,"branding":6,"contact":8,"organization_schema":10,"languages":54,"website":62,"docs":187,"blog":936},{"title":5},"Voldeno",{"logo":7,"company_name":5},"\u002Fimages\u002Flogo\u002Flogo_310.png",{"email":9},"contact@voldeno.com",{"schema_name":5,"legal_name":11,"founding_date":12,"tax_id":13,"identifiers":14,"address":21,"primary_email":9,"knows_about":26,"contact_points":39,"contact_point_available_languages":51},"Voldeno sp. z o.o.","2024","PL7252346262",[15,18],{"name":16,"value":17},"KRS","0001123648",{"name":19,"value":20},"REGON","52946949200000",{"street_address":22,"address_locality":23,"postal_code":24,"address_country":25},"Ogrodowa 8, Lobby B, 3p.","Łódź","91-062","PL",{"en":27,"pl":34},[28,29,30,31,32,33],"Smart Home","Smart Home Systems","Smart Home Automation","Building Automation","IoT","Home Automation System",[35,28,36,37,32,38],"Inteligentny dom","System Smart Home","Automatyka budynkowa","System automatyki domowej",[40,43,46,49],{"email":41,"contact_type":42},"support@voldeno.com","technical support",{"email":44,"contact_type":45},"sales@voldeno.com","sales",{"email":47,"contact_type":48},"partners@voldeno.com","partnerships",{"email":9,"contact_type":50},"customer service",[52,53],"Polish","English",[55,59],{"code":56,"name":57,"default":58},"pl","Polski",true,{"code":60,"name":53,"default":61},"en",false,{"enabled":58,"navigation":63,"path_keys":158,"section_index_slugs":180},{"pl":64,"en":121},[65,71,77,83,93,99,105,116],{"title":66,"slug":67,"path":68,"order":69,"template":70},"Smart Home, Automatyka budynkowa - Voldeno","index","pl\u002Findex",0,"home",{"title":72,"slug":73,"path":74,"order":75,"template":76},"Twój Dom","twoj-dom","pl\u002Ftwoj-dom",1,"homeowners",{"title":78,"slug":79,"path":80,"order":81,"template":82},"Dla Profesjonalistów","dla-profesjonalistow","pl\u002Fdla-profesjonalistow",2,"professionals",{"title":84,"slug":85,"path":86,"order":87,"children":88},"Produkty","produkty","pl\u002Fprodukty",3,[89],{"title":90,"slug":67,"path":91,"order":75,"template":92},"Inteligentne produkty​ Smart Home Voldeno","pl\u002Fprodukty\u002Findex","products",{"title":94,"slug":95,"path":96,"order":97,"template":98},"Kontakt","kontakt","pl\u002Fkontakt",4,"contact",{"title":100,"slug":101,"path":102,"order":103,"template":104},"O nas","o-nas","pl\u002Fo-nas",5,"about",{"title":106,"slug":107,"path":108,"order":109,"children":110},"Prawne","prawne","pl\u002Fprawne",6,[111],{"title":112,"slug":113,"path":114,"order":75,"template":115},"Polityka prywatności","polityka-prywatnosci","pl\u002Fprawne\u002Fpolityka-prywatnosci","page",{"title":117,"slug":118,"path":119,"order":120},"Realizacje","realizacje","pl\u002Frealizacje",999,[122,125,129,132,139,142,145,154],{"title":123,"slug":67,"path":124,"order":69,"template":70},"Voldeno: Smart Home, Building Automation","en\u002Findex",{"title":126,"slug":127,"path":128,"order":75,"template":76},"Your Home","your-home","en\u002Fyour-home",{"title":130,"slug":82,"path":131,"order":81,"template":82},"For Professionals","en\u002Fprofessionals",{"title":133,"slug":92,"path":134,"order":87,"children":135},"Products","en\u002Fproducts",[136],{"title":137,"slug":67,"path":138,"order":75,"template":92},"Smart Home Products​ from Voldeno","en\u002Fproducts\u002Findex",{"title":140,"slug":98,"path":141,"order":97,"template":98},"Contact","en\u002Fcontact",{"title":143,"slug":104,"path":144,"order":103,"template":104},"About Us","en\u002Fabout",{"title":146,"slug":147,"path":148,"order":109,"children":149},"Legal","legal","en\u002Flegal",[150],{"title":151,"slug":152,"path":153,"order":75,"template":115},"Privacy Policy","privacy-policy","en\u002Flegal\u002Fprivacy-policy",{"title":155,"slug":156,"path":157,"order":120},"Projects","projects","en\u002Fprojects",{"module_hub":159,"module_io":162,"module_1wire":165,"privacy":168,"downloads":171,"module_relay":174,"module_analog_input":177},{"pl":160,"en":161},"produkty\u002Fhub","products\u002Fhub",{"en":163,"pl":164},"products\u002Fio","produkty\u002Fio",{"pl":166,"en":167},"produkty\u002F1wire","products\u002F1wire",{"en":169,"pl":170},"legal\u002Fprivacy-policy","prawne\u002Fpolityka-prywatnosci",{"en":172,"pl":173},"downloads","pobieranie",{"pl":175,"en":176},"produkty\u002Frelay","products\u002Frelay",{"pl":178,"en":179},"produkty\u002Fanalog-input","products\u002Fanalog-input",{"en":181,"pl":184},{"products":182,"projects":183},"products\u002Findex","projects\u002Findex",{"realizacje":185,"produkty":186},"realizacje\u002Findex","produkty\u002Findex",{"enabled":58,"navigation":188,"section_redirects":909},{"en":189,"pl":645},[190,211,220,245,258,580,594,608,630,640],{"title":191,"slug":192,"path":193,"order":75,"children":194},"Getting Started","getting-started","en\u002Fdocs\u002Fgetting-started",[195,199,203,207],{"title":196,"slug":197,"path":198,"order":75},"Core Concepts and Terminology","concepts","en\u002Fdocs\u002Fgetting-started\u002Fconcepts",{"title":200,"slug":201,"path":202,"order":81},"System Overview for Installers","system-overview","en\u002Fdocs\u002Fgetting-started\u002Fsystem-overview",{"title":204,"slug":205,"path":206,"order":87},"How to define logic in Voldeno Studio from scratch","define-logic-in-voldeno-studio","en\u002Fdocs\u002Fgetting-started\u002Fdefine-logic-in-voldeno-studio",{"title":208,"slug":209,"path":210,"order":97},"Volang and VolangVM: why a smart home needs its own automation language","volang-and-volangvm","en\u002Fdocs\u002Fgetting-started\u002Fvolang-and-volangvm",{"title":212,"slug":213,"path":214,"order":81,"children":215},"System Architecture","system-architecture","en\u002Fdocs\u002Fsystem-architecture",[216],{"title":217,"slug":218,"path":219,"order":75},"Security Architecture","security","en\u002Fdocs\u002Fsystem-architecture\u002Fsecurity",{"title":221,"slug":222,"path":223,"order":87,"children":224},"Modules & Peripherals","modules","en\u002Fdocs\u002Fmodules",[225,229,233,237,241],{"title":226,"slug":227,"path":228,"order":75},"Hub Module Wiring","hub-wiring","en\u002Fdocs\u002Fmodules\u002Fhub-wiring",{"title":230,"slug":231,"path":232,"order":81},"I\u002FO Module Wiring","io-wiring","en\u002Fdocs\u002Fmodules\u002Fio-wiring",{"title":234,"slug":235,"path":236,"order":87},"Relay Module Wiring","relay-wiring","en\u002Fdocs\u002Fmodules\u002Frelay-wiring",{"title":238,"slug":239,"path":240,"order":97},"1-Wire Module Wiring","1wire-wiring","en\u002Fdocs\u002Fmodules\u002F1wire-wiring",{"title":242,"slug":243,"path":244,"order":103},"Analog Input Module Wiring","analog-input-wiring","en\u002Fdocs\u002Fmodules\u002Fanalog-input-wiring",{"title":246,"slug":247,"path":248,"order":97,"children":249},"Wiring Guidelines","wiring","en\u002Fdocs\u002Fwiring",[250,254],{"title":251,"slug":252,"path":253,"order":75},"Bus Topology & Wiring","bus-topology","en\u002Fdocs\u002Fwiring\u002Fbus-topology",{"title":255,"slug":256,"path":257,"order":81},"Power Supply Sizing and Distribution","power-supply","en\u002Fdocs\u002Fwiring\u002Fpower-supply",{"title":259,"slug":260,"path":261,"order":103,"children":262},"Logic Blocks","logic-blocks","en\u002Fdocs\u002Flogic-blocks",[263,269,320,565],{"title":264,"slug":265,"path":266,"order":69,"template":267,"translation_key":268},"Overview","overview","en\u002Fdocs\u002Flogic-blocks\u002Foverview","logic-block-index","logic-blocks-overview",{"title":270,"slug":271,"path":272,"order":75,"children":273},"Input","input","en\u002Fdocs\u002Flogic-blocks\u002Finput",[274,280,285,290,295,300,305,310,315],{"title":275,"slug":276,"path":277,"order":69,"template":278,"translation_key":279},"Binary input","binary_input","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fbinary_input","logic-block","logic-block-binary_input",{"title":281,"slug":282,"path":283,"order":69,"template":278,"translation_key":284},"Boolean constant","boolean_constant","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fboolean_constant","logic-block-boolean_constant",{"title":286,"slug":287,"path":288,"order":69,"template":278,"translation_key":289},"Numeric constant","numeric_constant","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fnumeric_constant","logic-block-numeric_constant",{"title":291,"slug":292,"path":293,"order":69,"template":278,"translation_key":294},"Numeric input","numeric_input","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fnumeric_input","logic-block-numeric_input",{"title":296,"slug":297,"path":298,"order":69,"template":278,"translation_key":299},"Mode monitor","operation_mode_monitor","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Foperation_mode_monitor","logic-block-operation_mode_monitor",{"title":301,"slug":302,"path":303,"order":69,"template":278,"translation_key":304},"PulseAt","pulse_at","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fpulse_at","logic-block-pulse_at",{"title":306,"slug":307,"path":308,"order":69,"template":278,"translation_key":309},"Schedule","schedule","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fschedule","logic-block-schedule",{"title":311,"slug":312,"path":313,"order":69,"template":278,"translation_key":314},"String constant","string_constant","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fstring_constant","logic-block-string_constant",{"title":316,"slug":317,"path":318,"order":69,"template":278,"translation_key":319},"Switch","switch","en\u002Fdocs\u002Flogic-blocks\u002Finput\u002Fswitch","logic-block-switch",{"title":321,"slug":322,"path":323,"order":81,"children":324},"Process","process","en\u002Fdocs\u002Flogic-blocks\u002Fprocess",[325,330,335,340,345,350,355,360,365,370,375,380,385,390,395,400,405,410,415,420,425,430,435,440,445,450,455,460,465,470,475,480,485,490,495,500,505,510,515,520,525,530,535,540,545,550,555,560],{"title":326,"slug":327,"path":328,"order":69,"template":278,"translation_key":329},"Binary limiter","binary_limiter","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fbinary_limiter","logic-block-binary_limiter",{"title":331,"slug":332,"path":333,"order":69,"template":278,"translation_key":334},"Boolean to string","boolean_to_string","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fboolean_to_string","logic-block-boolean_to_string",{"title":336,"slug":337,"path":338,"order":69,"template":278,"translation_key":339},"Climate regulator","climate_regulator","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fclimate_regulator","logic-block-climate_regulator",{"title":341,"slug":342,"path":343,"order":69,"template":278,"translation_key":344},"Climate regulator hub","climate_regulator_hub","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fclimate_regulator_hub","logic-block-climate_regulator_hub",{"title":346,"slug":347,"path":348,"order":69,"template":278,"translation_key":349},"Delay","delay","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fdelay","logic-block-delay",{"title":351,"slug":352,"path":353,"order":69,"template":278,"translation_key":354},"Delayed Pulse","delayed_pulse","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fdelayed_pulse","logic-block-delayed_pulse",{"title":356,"slug":357,"path":358,"order":69,"template":278,"translation_key":359},"Door, window","door_window_monitor","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fdoor_window_monitor","logic-block-door_window_monitor",{"title":361,"slug":362,"path":363,"order":69,"template":278,"translation_key":364},"Edge detector","edge_detector","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fedge_detector","logic-block-edge_detector",{"title":366,"slug":367,"path":368,"order":69,"template":278,"translation_key":369},"Gate","gate","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fgate","logic-block-gate",{"title":371,"slug":372,"path":373,"order":69,"template":278,"translation_key":374},"HTTP Request","http_request","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fhttp_request","logic-block-http_request",{"title":376,"slug":377,"path":378,"order":69,"template":278,"translation_key":379},"Hysteresis","hysteresis","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fhysteresis","logic-block-hysteresis",{"title":381,"slug":382,"path":383,"order":69,"template":278,"translation_key":384},"Irrigation","irrigation","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Firrigation","logic-block-irrigation",{"title":386,"slug":387,"path":388,"order":69,"template":278,"translation_key":389},"JSON Get Boolean","json_get_boolean","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fjson_get_boolean","logic-block-json_get_boolean",{"title":391,"slug":392,"path":393,"order":69,"template":278,"translation_key":394},"JSON Get Number","json_get_number","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fjson_get_number","logic-block-json_get_number",{"title":396,"slug":397,"path":398,"order":69,"template":278,"translation_key":399},"JSON Get String","json_get_string","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fjson_get_string","logic-block-json_get_string",{"title":401,"slug":402,"path":403,"order":69,"template":278,"translation_key":404},"Level to pulse","level_to_pulse","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Flevel_to_pulse","logic-block-level_to_pulse",{"title":406,"slug":407,"path":408,"order":69,"template":278,"translation_key":409},"Logic::And","logic_and","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Flogic_and","logic-block-logic_and",{"title":411,"slug":412,"path":413,"order":69,"template":278,"translation_key":414},"Logic::Not","logic_not","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Flogic_not","logic-block-logic_not",{"title":416,"slug":417,"path":418,"order":69,"template":278,"translation_key":419},"Logic::Or","logic_or","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Flogic_or","logic-block-logic_or",{"title":421,"slug":422,"path":423,"order":69,"template":278,"translation_key":424},"Math::Abs","math_abs","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_abs","logic-block-math_abs",{"title":426,"slug":427,"path":428,"order":69,"template":278,"translation_key":429},"Math::Add","math_add","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_add","logic-block-math_add",{"title":431,"slug":432,"path":433,"order":69,"template":278,"translation_key":434},"Math::Average","math_average","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_average","logic-block-math_average",{"title":436,"slug":437,"path":438,"order":69,"template":278,"translation_key":439},"Math::Ceil","math_ceil","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_ceil","logic-block-math_ceil",{"title":441,"slug":442,"path":443,"order":69,"template":278,"translation_key":444},"Math::Divide","math_divide","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_divide","logic-block-math_divide",{"title":446,"slug":447,"path":448,"order":69,"template":278,"translation_key":449},"Math::Floor","math_floor","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_floor","logic-block-math_floor",{"title":451,"slug":452,"path":453,"order":69,"template":278,"translation_key":454},"Math::Max","math_max","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_max","logic-block-math_max",{"title":456,"slug":457,"path":458,"order":69,"template":278,"translation_key":459},"Math::Min","math_min","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_min","logic-block-math_min",{"title":461,"slug":462,"path":463,"order":69,"template":278,"translation_key":464},"Math::Modulo","math_modulo","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_modulo","logic-block-math_modulo",{"title":466,"slug":467,"path":468,"order":69,"template":278,"translation_key":469},"Math::Multiply","math_multiply","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_multiply","logic-block-math_multiply",{"title":471,"slug":472,"path":473,"order":69,"template":278,"translation_key":474},"Math::Random","math_random","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_random","logic-block-math_random",{"title":476,"slug":477,"path":478,"order":69,"template":278,"translation_key":479},"Math::Round","math_round","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_round","logic-block-math_round",{"title":481,"slug":482,"path":483,"order":69,"template":278,"translation_key":484},"Math::Subtract","math_subtract","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmath_subtract","logic-block-math_subtract",{"title":486,"slug":487,"path":488,"order":69,"template":278,"translation_key":489},"Motor axis","motor_axis","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmotor_axis","logic-block-motor_axis",{"title":491,"slug":492,"path":493,"order":69,"template":278,"translation_key":494},"Moving average","moving_average","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fmoving_average","logic-block-moving_average",{"title":496,"slug":497,"path":498,"order":69,"template":278,"translation_key":499},"Number to string","number_to_string","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fnumber_to_string","logic-block-number_to_string",{"title":501,"slug":502,"path":503,"order":69,"template":278,"translation_key":504},"Numeric latch","numeric_latch","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fnumeric_latch","logic-block-numeric_latch",{"title":506,"slug":507,"path":508,"order":69,"template":278,"translation_key":509},"Numeric predicate","numeric_predicate","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fnumeric_predicate","logic-block-numeric_predicate",{"title":511,"slug":512,"path":513,"order":69,"template":278,"translation_key":514},"Numeric throttle","numeric_throttle","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fnumeric_throttle","logic-block-numeric_throttle",{"title":516,"slug":517,"path":518,"order":69,"template":278,"translation_key":519},"PubSub::Publish","pubsub","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fpubsub","logic-block-pubsub",{"title":521,"slug":522,"path":523,"order":69,"template":278,"translation_key":524},"Pulse counter","pulse_counter","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fpulse_counter","logic-block-pulse_counter",{"title":526,"slug":527,"path":528,"order":69,"template":278,"translation_key":529},"Pulse gate","pulse_gate","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fpulse_gate","logic-block-pulse_gate",{"title":531,"slug":532,"path":533,"order":69,"template":278,"translation_key":534},"Pulse throttle","pulse_throttle","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fpulse_throttle","logic-block-pulse_throttle",{"title":536,"slug":537,"path":538,"order":69,"template":278,"translation_key":539},"Sequencer","sequencer","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fsequencer","logic-block-sequencer",{"title":541,"slug":542,"path":543,"order":69,"template":278,"translation_key":544},"Shading","shading","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fshading","logic-block-shading",{"title":546,"slug":547,"path":548,"order":69,"template":278,"translation_key":549},"String format","string_format","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fstring_format","logic-block-string_format",{"title":551,"slug":552,"path":553,"order":69,"template":278,"translation_key":554},"String latch","string_latch","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fstring_latch","logic-block-string_latch",{"title":556,"slug":557,"path":558,"order":69,"template":278,"translation_key":559},"Toggle","toggle","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Ftoggle","logic-block-toggle",{"title":561,"slug":562,"path":563,"order":69,"template":278,"translation_key":564},"Variable Delayed Pulse","variable_delayed_pulse","en\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fvariable_delayed_pulse","logic-block-variable_delayed_pulse",{"title":566,"slug":567,"path":568,"order":87,"children":569},"Output","output","en\u002Fdocs\u002Flogic-blocks\u002Foutput",[570,575],{"title":571,"slug":572,"path":573,"order":69,"template":278,"translation_key":574},"Mode controller","operation_mode_controller","en\u002Fdocs\u002Flogic-blocks\u002Foutput\u002Foperation_mode_controller","logic-block-operation_mode_controller",{"title":576,"slug":577,"path":578,"order":69,"template":278,"translation_key":579},"Relay","relay","en\u002Fdocs\u002Flogic-blocks\u002Foutput\u002Frelay","logic-block-relay",{"title":581,"slug":582,"path":583,"order":109,"children":584},"Volang Programming Language","volang","en\u002Fdocs\u002Fvolang",[585,589],{"title":586,"slug":587,"path":588,"order":75},"The Volang Language","language","en\u002Fdocs\u002Fvolang\u002Flanguage",{"title":590,"slug":591,"path":592,"order":81,"template":593},"Standard Library","stdlib","en\u002Fdocs\u002Fvolang\u002Fstdlib","api-reference",{"title":595,"slug":596,"path":597,"order":598,"children":599},"Software & Tools","software","en\u002Fdocs\u002Fsoftware",7,[600,604],{"title":601,"slug":602,"path":603,"order":75},"Voldeno Studio - Installation and Walkthrough","studio","en\u002Fdocs\u002Fsoftware\u002Fstudio",{"title":605,"slug":606,"path":607,"order":81},"Voldeno Studio - Schedules","schedules","en\u002Fdocs\u002Fsoftware\u002Fschedules",{"title":609,"slug":610,"path":611,"order":612,"children":613},"How-to Guides & Recipes","how-to","en\u002Fdocs\u002Fhow-to",8,[614,618,622,626],{"title":615,"slug":616,"path":617,"order":75},"What is a smart home and how does it work?","what-is-a-smart-home","en\u002Fdocs\u002Fhow-to\u002Fwhat-is-a-smart-home",{"title":619,"slug":620,"path":621,"order":81},"How to choose a smart home system: a practical guide","how-to-choose-a-smart-home-system","en\u002Fdocs\u002Fhow-to\u002Fhow-to-choose-a-smart-home-system",{"title":623,"slug":624,"path":625,"order":87},"How much does a smart home cost? Three Voldeno installation variants with modules and prices","how-much-does-a-smart-home-cost","en\u002Fdocs\u002Fhow-to\u002Fhow-much-does-a-smart-home-cost",{"title":627,"slug":628,"path":629,"order":97},"7 most common smart home design mistakes","smart-home-design-mistakes","en\u002Fdocs\u002Fhow-to\u002Fsmart-home-design-mistakes",{"title":631,"slug":632,"path":633,"order":634,"children":635},"Troubleshooting & Diagnostics","troubleshooting","en\u002Fdocs\u002Ftroubleshooting",9,[636],{"title":637,"slug":638,"path":639,"order":75},"Bus Communication Troubleshooting","bus-communication","en\u002Fdocs\u002Ftroubleshooting\u002Fbus-communication",{"title":641,"slug":642,"path":643,"order":644},"Frequently Asked Questions","faq","en\u002Fdocs\u002Ffaq",10,[646,667,676,701,714,853,865,876,897,906],{"title":647,"slug":648,"path":649,"order":75,"children":650},"Pierwsze kroki","pierwsze-kroki","pl\u002Fdocs\u002Fpierwsze-kroki",[651,655,659,663],{"title":652,"slug":653,"path":654,"order":75},"Podstawowe pojęcia i terminologia","pojecia","pl\u002Fdocs\u002Fpierwsze-kroki\u002Fpojecia",{"title":656,"slug":657,"path":658,"order":81},"Przegląd systemu dla instalatorów","przeglad-systemu","pl\u002Fdocs\u002Fpierwsze-kroki\u002Fprzeglad-systemu",{"title":660,"slug":661,"path":662,"order":87},"Jak zdefiniować logikę w Voldeno Studio od zera","definiowanie-logiki-w-voldeno-studio","pl\u002Fdocs\u002Fpierwsze-kroki\u002Fdefiniowanie-logiki-w-voldeno-studio",{"title":664,"slug":665,"path":666,"order":97},"Volang i VolangVM: po co inteligentny dom potrzebuje własnego języka automatyki","volang-i-volangvm","pl\u002Fdocs\u002Fpierwsze-kroki\u002Fvolang-i-volangvm",{"title":668,"slug":669,"path":670,"order":81,"children":671},"Architektura systemu","architektura-systemu","pl\u002Fdocs\u002Farchitektura-systemu",[672],{"title":673,"slug":674,"path":675,"order":75},"Architektura bezpieczeństwa","bezpieczenstwo","pl\u002Fdocs\u002Farchitektura-systemu\u002Fbezpieczenstwo",{"title":677,"slug":678,"path":679,"order":87,"children":680},"Moduły i peryferia","moduly","pl\u002Fdocs\u002Fmoduly",[681,685,689,693,697],{"title":682,"slug":683,"path":684,"order":75},"Okablowanie modułu HUB","okablowanie-hub","pl\u002Fdocs\u002Fmoduly\u002Fokablowanie-hub",{"title":686,"slug":687,"path":688,"order":81},"Okablowanie modułu I\u002FO","okablowanie-io","pl\u002Fdocs\u002Fmoduly\u002Fokablowanie-io",{"title":690,"slug":691,"path":692,"order":87},"Okablowanie modułu RELAY","okablowanie-relay","pl\u002Fdocs\u002Fmoduly\u002Fokablowanie-relay",{"title":694,"slug":695,"path":696,"order":97},"Okablowanie modułu 1-Wire","okablowanie-1wire","pl\u002Fdocs\u002Fmoduly\u002Fokablowanie-1wire",{"title":698,"slug":699,"path":700,"order":103},"Okablowanie modułu Analog Input","okablowanie-analog-input","pl\u002Fdocs\u002Fmoduly\u002Fokablowanie-analog-input",{"title":702,"slug":703,"path":704,"order":97,"children":705},"Wytyczne okablowania","okablowanie","pl\u002Fdocs\u002Fokablowanie",[706,710],{"title":707,"slug":708,"path":709,"order":75},"Topologia i okablowanie magistrali","topologia-magistrali","pl\u002Fdocs\u002Fokablowanie\u002Ftopologia-magistrali",{"title":711,"slug":712,"path":713,"order":81},"Dobór i dystrybucja zasilania","zasilanie","pl\u002Fdocs\u002Fokablowanie\u002Fzasilanie",{"title":715,"slug":716,"path":717,"order":103,"children":718},"Bloki logiczne","bloki-logiczne","pl\u002Fdocs\u002Fbloki-logiczne",[719,723,745,845],{"title":720,"slug":721,"path":722,"order":69,"template":267,"translation_key":268},"Przegląd","przeglad","pl\u002Fdocs\u002Fbloki-logiczne\u002Fprzeglad",{"title":724,"slug":271,"path":725,"order":75,"children":726},"Wejścia","pl\u002Fdocs\u002Fbloki-logiczne\u002Finput",[727,729,731,733,735,737,739,741,743],{"title":275,"slug":276,"path":728,"order":69,"template":278,"translation_key":279},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fbinary_input",{"title":281,"slug":282,"path":730,"order":69,"template":278,"translation_key":284},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fboolean_constant",{"title":286,"slug":287,"path":732,"order":69,"template":278,"translation_key":289},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fnumeric_constant",{"title":291,"slug":292,"path":734,"order":69,"template":278,"translation_key":294},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fnumeric_input",{"title":296,"slug":297,"path":736,"order":69,"template":278,"translation_key":299},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Foperation_mode_monitor",{"title":301,"slug":302,"path":738,"order":69,"template":278,"translation_key":304},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fpulse_at",{"title":306,"slug":307,"path":740,"order":69,"template":278,"translation_key":309},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fschedule",{"title":311,"slug":312,"path":742,"order":69,"template":278,"translation_key":314},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fstring_constant",{"title":316,"slug":317,"path":744,"order":69,"template":278,"translation_key":319},"pl\u002Fdocs\u002Fbloki-logiczne\u002Finput\u002Fswitch",{"title":746,"slug":322,"path":747,"order":81,"children":748},"Przetwarzanie","pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess",[749,751,753,755,757,759,761,763,765,767,769,771,773,775,777,779,781,783,785,787,789,791,793,795,797,799,801,803,805,807,809,811,813,815,817,819,821,823,825,827,829,831,833,835,837,839,841,843],{"title":326,"slug":327,"path":750,"order":69,"template":278,"translation_key":329},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fbinary_limiter",{"title":331,"slug":332,"path":752,"order":69,"template":278,"translation_key":334},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fboolean_to_string",{"title":336,"slug":337,"path":754,"order":69,"template":278,"translation_key":339},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fclimate_regulator",{"title":341,"slug":342,"path":756,"order":69,"template":278,"translation_key":344},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fclimate_regulator_hub",{"title":346,"slug":347,"path":758,"order":69,"template":278,"translation_key":349},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fdelay",{"title":351,"slug":352,"path":760,"order":69,"template":278,"translation_key":354},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fdelayed_pulse",{"title":356,"slug":357,"path":762,"order":69,"template":278,"translation_key":359},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fdoor_window_monitor",{"title":361,"slug":362,"path":764,"order":69,"template":278,"translation_key":364},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fedge_detector",{"title":366,"slug":367,"path":766,"order":69,"template":278,"translation_key":369},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fgate",{"title":371,"slug":372,"path":768,"order":69,"template":278,"translation_key":374},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fhttp_request",{"title":376,"slug":377,"path":770,"order":69,"template":278,"translation_key":379},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fhysteresis",{"title":381,"slug":382,"path":772,"order":69,"template":278,"translation_key":384},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Firrigation",{"title":386,"slug":387,"path":774,"order":69,"template":278,"translation_key":389},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fjson_get_boolean",{"title":391,"slug":392,"path":776,"order":69,"template":278,"translation_key":394},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fjson_get_number",{"title":396,"slug":397,"path":778,"order":69,"template":278,"translation_key":399},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fjson_get_string",{"title":401,"slug":402,"path":780,"order":69,"template":278,"translation_key":404},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Flevel_to_pulse",{"title":406,"slug":407,"path":782,"order":69,"template":278,"translation_key":409},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Flogic_and",{"title":411,"slug":412,"path":784,"order":69,"template":278,"translation_key":414},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Flogic_not",{"title":416,"slug":417,"path":786,"order":69,"template":278,"translation_key":419},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Flogic_or",{"title":421,"slug":422,"path":788,"order":69,"template":278,"translation_key":424},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_abs",{"title":426,"slug":427,"path":790,"order":69,"template":278,"translation_key":429},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_add",{"title":431,"slug":432,"path":792,"order":69,"template":278,"translation_key":434},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_average",{"title":436,"slug":437,"path":794,"order":69,"template":278,"translation_key":439},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_ceil",{"title":441,"slug":442,"path":796,"order":69,"template":278,"translation_key":444},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_divide",{"title":446,"slug":447,"path":798,"order":69,"template":278,"translation_key":449},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_floor",{"title":451,"slug":452,"path":800,"order":69,"template":278,"translation_key":454},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_max",{"title":456,"slug":457,"path":802,"order":69,"template":278,"translation_key":459},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_min",{"title":461,"slug":462,"path":804,"order":69,"template":278,"translation_key":464},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_modulo",{"title":466,"slug":467,"path":806,"order":69,"template":278,"translation_key":469},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_multiply",{"title":471,"slug":472,"path":808,"order":69,"template":278,"translation_key":474},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_random",{"title":476,"slug":477,"path":810,"order":69,"template":278,"translation_key":479},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_round",{"title":481,"slug":482,"path":812,"order":69,"template":278,"translation_key":484},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmath_subtract",{"title":486,"slug":487,"path":814,"order":69,"template":278,"translation_key":489},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmotor_axis",{"title":491,"slug":492,"path":816,"order":69,"template":278,"translation_key":494},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fmoving_average",{"title":496,"slug":497,"path":818,"order":69,"template":278,"translation_key":499},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fnumber_to_string",{"title":501,"slug":502,"path":820,"order":69,"template":278,"translation_key":504},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fnumeric_latch",{"title":506,"slug":507,"path":822,"order":69,"template":278,"translation_key":509},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fnumeric_predicate",{"title":511,"slug":512,"path":824,"order":69,"template":278,"translation_key":514},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fnumeric_throttle",{"title":516,"slug":517,"path":826,"order":69,"template":278,"translation_key":519},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fpubsub",{"title":521,"slug":522,"path":828,"order":69,"template":278,"translation_key":524},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fpulse_counter",{"title":526,"slug":527,"path":830,"order":69,"template":278,"translation_key":529},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fpulse_gate",{"title":531,"slug":532,"path":832,"order":69,"template":278,"translation_key":534},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fpulse_throttle",{"title":536,"slug":537,"path":834,"order":69,"template":278,"translation_key":539},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fsequencer",{"title":541,"slug":542,"path":836,"order":69,"template":278,"translation_key":544},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fshading",{"title":546,"slug":547,"path":838,"order":69,"template":278,"translation_key":549},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fstring_format",{"title":551,"slug":552,"path":840,"order":69,"template":278,"translation_key":554},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fstring_latch",{"title":556,"slug":557,"path":842,"order":69,"template":278,"translation_key":559},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Ftoggle",{"title":561,"slug":562,"path":844,"order":69,"template":278,"translation_key":564},"pl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fvariable_delayed_pulse",{"title":846,"slug":567,"path":847,"order":87,"children":848},"Wyjścia","pl\u002Fdocs\u002Fbloki-logiczne\u002Foutput",[849,851],{"title":571,"slug":572,"path":850,"order":69,"template":278,"translation_key":574},"pl\u002Fdocs\u002Fbloki-logiczne\u002Foutput\u002Foperation_mode_controller",{"title":576,"slug":577,"path":852,"order":69,"template":278,"translation_key":579},"pl\u002Fdocs\u002Fbloki-logiczne\u002Foutput\u002Frelay",{"title":854,"slug":582,"path":855,"order":109,"children":856},"Język programowania Volang","pl\u002Fdocs\u002Fvolang",[857,861],{"title":858,"slug":859,"path":860,"order":75},"Język Volang","jezyk","pl\u002Fdocs\u002Fvolang\u002Fjezyk",{"title":862,"slug":863,"path":864,"order":81,"template":593},"Biblioteka standardowa","biblioteka-standardowa","pl\u002Fdocs\u002Fvolang\u002Fbiblioteka-standardowa",{"title":866,"slug":867,"path":868,"order":598,"children":869},"Oprogramowanie","oprogramowanie","pl\u002Fdocs\u002Foprogramowanie",[870,873],{"title":871,"slug":602,"path":872,"order":75},"Voldeno Studio - Instalacja i przewodnik","pl\u002Fdocs\u002Foprogramowanie\u002Fstudio",{"title":874,"slug":606,"path":875,"order":81},"Voldeno Studio - Harmonogramy","pl\u002Fdocs\u002Foprogramowanie\u002Fschedules",{"title":877,"slug":878,"path":879,"order":612,"children":880},"Poradniki","poradniki","pl\u002Fdocs\u002Fporadniki",[881,885,889,893],{"title":882,"slug":883,"path":884,"order":75},"Czym jest smart home i jak działa?","czym-jest-smart-home","pl\u002Fdocs\u002Fporadniki\u002Fczym-jest-smart-home",{"title":886,"slug":887,"path":888,"order":81},"Jaki system smart home wybrać? Praktyczny przewodnik","jaki-system-smart-home-wybrac","pl\u002Fdocs\u002Fporadniki\u002Fjaki-system-smart-home-wybrac",{"title":890,"slug":891,"path":892,"order":87},"Ile kosztuje inteligentny dom? Trzy warianty instalacji Voldeno z modułami i cenami","ile-kosztuje-inteligentny-dom","pl\u002Fdocs\u002Fporadniki\u002File-kosztuje-inteligentny-dom",{"title":894,"slug":895,"path":896,"order":97},"7 najczęstszych błędów przy projektowaniu instalacji smart home","bledy-przy-projektowaniu-smart-home","pl\u002Fdocs\u002Fporadniki\u002Fbledy-przy-projektowaniu-smart-home",{"title":898,"slug":899,"path":900,"order":634,"children":901},"Diagnostyka i rozwiązywanie problemów","diagnostyka","pl\u002Fdocs\u002Fdiagnostyka",[902],{"title":903,"slug":904,"path":905,"order":75},"Rozwiązywanie problemów z komunikacją magistrali","komunikacja-magistrali","pl\u002Fdocs\u002Fdiagnostyka\u002Fkomunikacja-magistrali",{"title":907,"slug":642,"path":908,"order":644},"Często zadawane pytania","pl\u002Fdocs\u002Ffaq",{"en":910,"pl":923},{"wiring":911,"logic-blocks\u002Fprocess":912,"modules":913,"volang":914,"software":915,"logic-blocks":916,"troubleshooting":917,"how-to":918,"getting-started":919,"system-architecture":920,"logic-blocks\u002Foutput":921,"logic-blocks\u002Finput":922},"wiring\u002Fbus-topology","logic-blocks\u002Fprocess\u002Fbinary_limiter","modules\u002Fhub-wiring","volang\u002Flanguage","software\u002Fstudio","logic-blocks\u002Foverview","troubleshooting\u002Fbus-communication","how-to\u002Fwhat-is-a-smart-home","getting-started\u002Fconcepts","system-architecture\u002Fsecurity","logic-blocks\u002Foutput\u002Foperation_mode_controller","logic-blocks\u002Finput\u002Fbinary_input",{"bloki-logiczne":924,"okablowanie":925,"bloki-logiczne\u002Finput":926,"pierwsze-kroki":927,"moduly":928,"bloki-logiczne\u002Foutput":929,"diagnostyka":930,"bloki-logiczne\u002Fprocess":931,"architektura-systemu":932,"oprogramowanie":933,"poradniki":934,"volang":935},"bloki-logiczne\u002Fprzeglad","okablowanie\u002Ftopologia-magistrali","bloki-logiczne\u002Finput\u002Fbinary_input","pierwsze-kroki\u002Fpojecia","moduly\u002Fokablowanie-hub","bloki-logiczne\u002Foutput\u002Foperation_mode_controller","diagnostyka\u002Fkomunikacja-magistrali","bloki-logiczne\u002Fprocess\u002Fbinary_limiter","architektura-systemu\u002Fbezpieczenstwo","oprogramowanie\u002Fstudio","poradniki\u002Fczym-jest-smart-home","volang\u002Fjezyk",{"enabled":58,"navigation":937},{"pl":938,"en":969},[939,945,951,957,963],{"title":940,"slug":941,"path":942,"order":69,"date":943,"translation_key":944},"Przełączanie w zerze napięcia: jak moduły I\u002FO i RELAY wydłużają życie styków przekaźników","przelaczanie-w-zerze-napiecia-moduly-io-i-relay","pl\u002Fblog\u002Fprzelaczanie-w-zerze-napiecia-moduly-io-i-relay","2026-06-11","2026_06_11_przelaczanie_w_zerze_napiecia",{"title":946,"slug":947,"path":948,"order":69,"date":949,"translation_key":950},"System Voldeno napędził demo fabryki Fischertechnik na Google Cloud Next '26","voldeno-at-google-cloud-next-26","pl\u002Fblog\u002Fvoldeno-at-google-cloud-next-26","2026-04-28","2026_04_28_voldeno_at_google_cloud_next_26",{"title":952,"slug":953,"path":954,"order":69,"date":955,"translation_key":956},"Jesteśmy gotowi! Setki modułów Voldeno przygotowanych do wdrożenia w inteligentnych domach.","jestesmy-gotowi-setki-modulow-voldeno-przygotowanych-do-wdrozenia-w-inteligentnych-domach","pl\u002Fblog\u002Fjestesmy-gotowi-setki-modulow-voldeno-przygotowanych-do-wdrozenia-w-inteligentnych-domach","2025-08-17","2025_08_17_we_are_ready",{"title":958,"slug":959,"path":960,"order":69,"date":961,"translation_key":962},"Nowy czujnik temperatury Voldeno 1-Wire - kompaktowy, niezawodny i stworzony do dużych instalacji","nowy-czujnik-temperatury-1-wire-voldeno-kompaktowy-niezawodny-i-zaprojektowany-do-instalacji-na-duza-skale","pl\u002Fblog\u002Fnowy-czujnik-temperatury-1-wire-voldeno-kompaktowy-niezawodny-i-zaprojektowany-do-instalacji-na-duza-skale","2025-04-25","2025_04_25_new_voldeno_1wire_temperature_sensor",{"title":964,"slug":965,"path":966,"order":69,"date":967,"translation_key":968},"Odkryj przyszłość inteligentnych domów z Voldeno","odkryj-przyszlosc-inteligentnych-domow-z-voldeno","pl\u002Fblog\u002Fodkryj-przyszlosc-inteligentnych-domow-z-voldeno","2024-10-18","2024_10_18_future_of_smart_homes",[970,975,978,982,986],{"title":971,"slug":972,"path":973,"order":69,"date":943,"translation_key":974},"Zero-crossing switching: how the I\u002FO and RELAY modules extend relay contact life","zero-crossing-switching-io-and-relay-modules","en\u002Fblog\u002Fzero-crossing-switching-io-and-relay-modules","2026_06_11_zero_crossing_switching",{"title":976,"slug":947,"path":977,"order":69,"date":949,"translation_key":950},"Voldeno powered the Fischertechnik factory demo at Google Cloud Next '26","en\u002Fblog\u002Fvoldeno-at-google-cloud-next-26",{"title":979,"slug":980,"path":981,"order":69,"date":955,"translation_key":956},"We are ready! Hundreds of Voldeno modules prepared for smart home deployment.","we-are-ready","en\u002Fblog\u002Fwe-are-ready",{"title":983,"slug":984,"path":985,"order":69,"date":961,"translation_key":962},"New Voldeno 1-Wire Temperature Sensor - Compact, Reliable, and Built for Large-Scale Installations","new-voldeno-1-wire-temperature-sensor-compact-reliable-and-built-for-large-scale-installations","en\u002Fblog\u002Fnew-voldeno-1-wire-temperature-sensor-compact-reliable-and-built-for-large-scale-installations",{"title":987,"slug":988,"path":989,"order":69,"date":967,"translation_key":968},"Discover the Future of Smart Homes with Voldeno","future_of_smart_homes","en\u002Fblog\u002Ffuture_of_smart_homes",{"pl":991,"en":992,"xDefault":991},"https:\u002F\u002Fvoldeno.com\u002Fpl\u002Fdocs\u002Fbloki-logiczne\u002Fprocess\u002Fgate","https:\u002F\u002Fvoldeno.com\u002Fen\u002Fdocs\u002Flogic-blocks\u002Fprocess\u002Fgate",{"slug":367,"title":366,"description":994,"tags":995,"content_html":996,"headings":997,"template":278,"extra":1011},"Poznaj działanie bloku logicznego Gate - zasada działania, opcje konfiguracji i przykłady zastosowań w Voldeno.",[260,322,367],"\u003Ch1 id=\"gate\">\u003Ca href=\"#gate\" class=\"anchor\">#\u003C\u002Fa> Gate\u003C\u002Fh1>\n\u003Cdiv class=\"block-meta\">\n  \u003Cspan class=\"badge badge-group badge-group-process\">Przetwarzanie\u003C\u002Fspan>\n\u003C\u002Fdiv>\n\n\u003Cp class=\"block-description\">Steruje bramami i bramami garażowymi, bezpośrednio lub przez zewnętrzny sterownik bramy\u003C\u002Fp>\n\u003C!-- BLOCK_DIAGRAM -->\n\u003Ch2 id=\"source-code\">\u003Ca href=\"#source-code\" class=\"anchor\">#\u003C\u002Fa> Kod źródłowy\u003C\u002Fh2>\n\u003Cdetails class=\"code-details\">\u003Csummary>Pokaż kod Volang\u003C\u002Fsummary>\n\u003Cdiv class=\"code-block\" data-lang=\"volang\">\n\u003Cpre>\u003Ccode class=\"language-volang\">\u003Cspan class=\"comment\">\u002F\u002F Gate \u002F garage door controller.\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F Control modes (config control_mode):\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   0 - Direct motor control: open\u002Fclose outputs are level signals driving the motor\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   1 - Single control output, controller cycles open\u002Fstop\u002Fclose\u002Fstop on each pulse (3F)\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   2 - Single control output, controller toggles open\u002Fclose on each pulse (no stop)\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   3 - Separate pulse outputs for open and close; the controller function behind each\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F       output is configured with open_output_function \u002F close_output_function:\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F       0 - Open (Ot), 1 - Close (ZA), 2 - Open\u002FClose (OZ), 3 - Open\u002FStop\u002FClose (3F),\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F       4 - Partial open (U), 5 - Partial open\u002FClose (PC)\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F gate_state output values:\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   0 - closed, 1 - opening, 2 - open, 3 - closing, 4 - stopped midway, 5 - partially open\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F desired_action state values:\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   0 - none, 1 - open, 2 - close, 3 - stop,\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   4 - partial open through a controller channel (dedicated partial pulse, or a\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F       close pulse on a closed gate for the Partial open\u002FClose function),\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F   5 - raw control pulse (hardware toggle pass-through)\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F Position is simulated from opening\u002Fclosing durations on a 100ms tick and corrected\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F by the is_open \u002F is_closed limit switch inputs when they are connected.\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F motor_lock_duration is the time the motor needs to reverse direction. In direct mode it\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F keeps the motor off for that time (motor protection); in the non-direct modes the\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F controller owns the motor, so the lock instead holds the simulated position for the\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F reversal window so the position estimate accounts for the time a reversal takes.\u003C\u002Fspan>\n\n\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::channel\u003C\u002Fspan>()\n\u003Cspan class=\"variable\">value\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::value\u003C\u002Fspan>()\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">ticks_for\u003C\u002Fspan>(\u003Cspan class=\"variable\">seconds\u003C\u002Fspan>) {\n    \u003Cspan class=\"variable\">t\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">math::round\u003C\u002Fspan>((\u003Cspan class=\"variable\">seconds\u003C\u002Fspan> \u003Cspan class=\"operator\">*\u003C\u002Fspan> \u003Cspan class=\"number\">1000\u003C\u002Fspan>) \u003Cspan class=\"operator\">\u002F\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">t\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">t\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"variable\">t\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"comment\">\u002F\u002F Position margin (percent) within which a limit-switch re-assert right after the\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F gate departs that limit is treated as contact bounce rather than a real arrival.\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F Outside this margin the sensor is always trusted, so remote \u002F external movement\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F that drives the gate back to a limit is honored.\u003C\u002Fspan>\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">sensor_bounce_margin\u003C\u002Fspan>() {\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"number\">5\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"variable\">s\u003C\u002Fspan>) {\n    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"gate_state\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">s\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">apply_stopped_state\u003C\u002Fspan>() {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n        \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;=\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n        \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">4\u003C\u002Fspan>)\n    }\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"variable\">d\u003C\u002Fspan>) {\n    \u003Cspan class=\"variable\">prev_dir\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_dir\"\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">d\u003C\u002Fspan>)\n    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F A direction reversal costs the motor lock time regardless of the control mode.\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F In direct mode the motor is physically held off for that time (handled in\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F process_desired). In the non-direct modes the controller owns the motor, so the\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F pulse is sent right away, but the gate still needs that time to reverse - hold the\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F simulated position for the remaining lock window so the estimate stays accurate.\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">prev_dir\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"variable\">d\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">lock_ms\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">math::round\u003C\u002Fspan>(\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"motor_lock_duration\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">*\u003C\u002Fspan> \u003Cspan class=\"number\">1000\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">since\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">time::uptime\u003C\u002Fspan>() \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_movement_ts\"\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">since\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"variable\">lock_ms\u003C\u002Fspan>) {\n                \u003Cspan class=\"variable\">lt\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">math::round\u003C\u002Fspan>((\u003Cspan class=\"variable\">lock_ms\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"variable\">since\u003C\u002Fspan>) \u003Cspan class=\"operator\">\u002F\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>)\n                \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">lt\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n                    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"move_lock_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">lt\u003C\u002Fspan>)\n                }\n            }\n        }\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_dir\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">d\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_movement_ts\"\u003C\u002Fspan>, \u003Cspan class=\"stdlib\">time::uptime\u003C\u002Fspan>())\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n        }\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"move_lock_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    }\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">direct_apply\u003C\u002Fspan>(\u003Cspan class=\"variable\">d\u003C\u002Fspan>) {\n    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"open\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"close\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">pulse_output_name\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">out_id\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"string\">\"control\"\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">out_id\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"string\">\"open\"\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"string\">\"close\"\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">cycle_state_name\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">out_id\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"string\">\"cycle_next\"\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">out_id\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"string\">\"cycle_next_op\"\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"string\">\"cycle_next_cl\"\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"comment\">\u002F\u002F Returns the pulse output (2=open, 3=close) whose controller function matches f,\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F or 0 when none is configured. Used in separate pulses mode only.\u003C\u002Fspan>\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"variable\">f\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"open_output_function\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"variable\">f\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"close_output_function\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"variable\">f\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"comment\">\u002F\u002F Mirror what the external controller does when it receives a pulse\u003C\u002Fspan>\n\u003Cspan class=\"comment\">\u002F\u002F on a channel configured with the given function\u003C\u002Fspan>\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">apply_channel_function\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>, \u003Cspan class=\"variable\">f\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">f\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F open\u003C\u002Fspan>\n        \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">f\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F close\u003C\u002Fspan>\n        \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">f\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F open\u002Fclose toggle\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"variable\">d\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">f\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F open\u002Fstop\u002Fclose\u002Fstop cycle, tracked per channel\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">a\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"function\">cycle_state_name\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>))\n        \u003Cspan class=\"variable\">nxt\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">a\u003C\u002Fspan> \u003Cspan class=\"operator\">+\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">nxt\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">nxt\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"function\">cycle_state_name\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>), \u003Cspan class=\"variable\">nxt\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">a\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">a\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">apply_stopped_state\u003C\u002Fspan>()\n        }\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">f\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">4\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F partial open - controller moves the gate to its partial position\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">ppos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_open_position\"\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;\u003C\u002Fspan> \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"comment\">\u002F\u002F f == 5: partial open \u002F close\u003C\u002Fspan>\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F controller interprets a pulse on a closed gate as partial open\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_open_position\"\u003C\u002Fspan>))\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n        \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n        \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    }\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">apply_pulse_semantics\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>) {\n    \u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F single control output with open\u002Fstop\u002Fclose cycle\u003C\u002Fspan>\n        \u003Cspan class=\"function\">apply_channel_function\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>, \u003Cspan class=\"number\">3\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F single control output with open\u002Fclose toggle\u003C\u002Fspan>\n        \u003Cspan class=\"function\">apply_channel_function\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"comment\">\u002F\u002F separate pulses - behaviour depends on the configured channel function\u003C\u002Fspan>\n    \u003Cspan class=\"variable\">f\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"open_output_function\"\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">out_id\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">f\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"close_output_function\"\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"function\">apply_channel_function\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>, \u003Cspan class=\"variable\">f\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>) {\n    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"function\">pulse_output_name\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>), \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_out\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">out_id\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>, \u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"function\">ticks_for\u003C\u002Fspan>(\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_duration\"\u003C\u002Fspan>)))\n    \u003Cspan class=\"function\">apply_pulse_semantics\u003C\u002Fspan>(\u003Cspan class=\"variable\">out_id\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">process_desired\u003C\u002Fspan>() {\n    \u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>)\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">5\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F hardware toggle pass-through\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"variable\">ch\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">4\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F partial open through a controller channel\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">4\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"variable\">ch\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"comment\">\u002F\u002F already satisfied?\u003C\u002Fspan>\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">&gt;=\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>)) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>)) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"comment\">\u002F\u002F safety sensors\u003C\u002Fspan>\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_open\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F direct motor control\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">direct_apply\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">apply_stopped_state\u003C\u002Fspan>()\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n\n        \u003Cspan class=\"variable\">new_dir\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">new_dir\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>\n        }\n\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F direction change - stop the motor first\u003C\u002Fspan>\n            \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">direct_apply\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">apply_stopped_state\u003C\u002Fspan>()\n        }\n\n        \u003Cspan class=\"variable\">lock_ms\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">math::round\u003C\u002Fspan>(\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"motor_lock_duration\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">*\u003C\u002Fspan> \u003Cspan class=\"number\">1000\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">since\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">time::uptime\u003C\u002Fspan>() \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_movement_ts\"\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">since\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"variable\">lock_ms\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"variable\">new_dir\u003C\u002Fspan>) {\n            \u003Cspan class=\"comment\">\u002F\u002F wait for the motor lock to release, then retry (desired_action is kept)\u003C\u002Fspan>\n            \u003Cspan class=\"variable\">lock_ticks\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"stdlib\">math::round\u003C\u002Fspan>((\u003Cspan class=\"variable\">lock_ms\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"variable\">since\u003C\u002Fspan>) \u003Cspan class=\"operator\">\u002F\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">lock_ticks\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n                \u003Cspan class=\"variable\">lock_ticks\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>\n            }\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">lock_ticks\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n\n        \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"variable\">new_dir\u003C\u002Fspan>)\n        \u003Cspan class=\"function\">direct_apply\u003C\u002Fspan>(\u003Cspan class=\"variable\">new_dir\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F keep pulsing through the controller cycle until the desired action is applied\u003C\u002Fspan>\n        \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F open\u002Fclose toggle - stop is not available\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"comment\">\u002F\u002F separate pulses - pick a channel that can perform the desired action\u003C\u002Fspan>\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>) \u003Cspan class=\"comment\">\u002F\u002F only an open\u002Fstop\u002Fclose channel can stop\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"variable\">ch\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">desired\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"variable\">ch\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">ch\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"function\">emit_pulse\u003C\u002Fspan>(\u003Cspan class=\"variable\">ch\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">ensure_tick\u003C\u002Fspan>() {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"tick_active\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"tick_active\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n    \u003Cspan class=\"stdlib\">callback::set\u003C\u002Fspan>(\u003Cspan class=\"number\">99\u003C\u002Fspan>, \u003Cspan class=\"string\">\"onTick\"\u003C\u002Fspan>) \u003Cspan class=\"comment\">\u002F\u002F 99 instead of 100 to leave room for callback scheduling\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"variable\">action\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">action\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">4\u003C\u002Fspan>) { \u003Cspan class=\"comment\">\u002F\u002F any new command cancels a pending partial-open target\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target_stop_needed\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_after_close\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">action\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">process_desired\u003C\u002Fspan>()\n    }\n    \u003Cspan class=\"function\">ensure_tick\u003C\u002Fspan>()\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">reach_open_end\u003C\u002Fspan>() {\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">100.0\u003C\u002Fspan>)\n    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">100\u003C\u002Fspan>)\n    \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">direct_apply\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"comment\">\u002F\u002F limit reached - a cycling controller continues with the closing direction\u003C\u002Fspan>\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"cycle_next\"\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"cycle_next_op\"\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"cycle_next_cl\"\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target_stop_needed\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_after_close\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n    \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">reach_closed_end\u003C\u002Fspan>() {\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0.0\u003C\u002Fspan>)\n    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">direct_apply\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"comment\">\u002F\u002F limit reached - a cycling controller continues with the opening direction\u003C\u002Fspan>\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"cycle_next\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"cycle_next_op\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"cycle_next_cl\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target_stop_needed\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n    \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n    \u003Cspan class=\"comment\">\u002F\u002F if a two-phase partial open was waiting for the gate to be fully closed,\u003C\u002Fspan>\n    \u003Cspan class=\"comment\">\u002F\u002F now issue the partial open pulse (PC channel interprets it as partial open)\u003C\u002Fspan>\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_after_close\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_after_close\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">4\u003C\u002Fspan>)\n    }\n}\n\n\u003Cspan class=\"keyword\">extern\u003C\u002Fspan> \u003Cspan class=\"keyword\">fn\u003C\u002Fspan> \u003Cspan class=\"function\">onTick\u003C\u002Fspan>() {\n    \u003Cspan class=\"comment\">\u002F\u002F pulse \u002F pause \u002F motor lock phases\u003C\u002Fspan>\n    \u003Cspan class=\"variable\">phase\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">phase\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">t\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">t\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"function\">pulse_output_name\u003C\u002Fspan>(\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_out\"\u003C\u002Fspan>)), \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_out\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"function\">ticks_for\u003C\u002Fspan>(\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_pause\"\u003C\u002Fspan>)))\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">t\u003C\u002Fspan>)\n        }\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">phase\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">t\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">t\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n            \u003Cspan class=\"function\">process_desired\u003C\u002Fspan>()\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">t\u003C\u002Fspan>)\n        }\n    }\n\n    \u003Cspan class=\"comment\">\u002F\u002F movement simulation; position is frozen while a stop pulse is pending\u003C\u002Fspan>\n    \u003Cspan class=\"comment\">\u002F\u002F (the gate is about to be stopped, waiting only for the pulse machinery)\u003C\u002Fspan>\n    \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>)\n    \u003Cspan class=\"comment\">\u002F\u002F reversal dead-time: in the non-direct modes the position is held while the motor\u003C\u002Fspan>\n    \u003Cspan class=\"comment\">\u002F\u002F lock is still elapsing, because the gate cannot have changed direction yet\u003C\u002Fspan>\n    \u003Cspan class=\"variable\">move_lock\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"move_lock_ticks\"\u003C\u002Fspan>)\n    \u003Cspan class=\"comment\">\u002F\u002F in sensor mode, position does not advance while the departure sensor is still\u003C\u002Fspan>\n    \u003Cspan class=\"comment\">\u002F\u002F asserted: the gate may not have physically left the limit yet (e.g. power\u003C\u002Fspan>\n    \u003Cspan class=\"comment\">\u002F\u002F failure, stalled motor) and the sensor is the authoritative source\u003C\u002Fspan>\n    \u003Cspan class=\"variable\">sensor_holds_pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">false\u003C\u002Fspan>\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"use_sensors\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"is_closed\"\u003C\u002Fspan>)) {\n            \u003Cspan class=\"variable\">sensor_holds_pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">true\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"is_open\"\u003C\u002Fspan>)) {\n            \u003Cspan class=\"variable\">sensor_holds_pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">true\u003C\u002Fspan>\n        }\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">move_lock\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"move_lock_ticks\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">move_lock\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"operator\">!\u003C\u002Fspan>\u003Cspan class=\"variable\">sensor_holds_pos\u003C\u002Fspan>) {\n        \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">+\u003C\u002Fspan> (\u003Cspan class=\"number\">100\u003C\u002Fspan> \u003Cspan class=\"operator\">*\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>) \u003Cspan class=\"operator\">\u002F\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"opening_duration\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">*\u003C\u002Fspan> \u003Cspan class=\"number\">1000.0\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> (\u003Cspan class=\"number\">100\u003C\u002Fspan> \u003Cspan class=\"operator\">*\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>) \u003Cspan class=\"operator\">\u002F\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"closing_duration\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">*\u003C\u002Fspan> \u003Cspan class=\"number\">1000.0\u003C\u002Fspan>)\n        }\n\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;=\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>) {\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"use_sensors\"\u003C\u002Fspan>)) {\n                \u003Cspan class=\"comment\">\u002F\u002F clamp for display; actual end-of-travel is confirmed by the is_open sensor\u003C\u002Fspan>\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">100.0\u003C\u002Fspan>)\n                \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">100\u003C\u002Fspan>)\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_movement_ts\"\u003C\u002Fspan>, \u003Cspan class=\"stdlib\">time::uptime\u003C\u002Fspan>())\n            } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n                \u003Cspan class=\"function\">reach_open_end\u003C\u002Fspan>()\n            }\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"use_sensors\"\u003C\u002Fspan>)) {\n                \u003Cspan class=\"comment\">\u002F\u002F clamp for display; actual end-of-travel is confirmed by the is_closed sensor\u003C\u002Fspan>\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0.0\u003C\u002Fspan>)\n                \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_movement_ts\"\u003C\u002Fspan>, \u003Cspan class=\"stdlib\">time::uptime\u003C\u002Fspan>())\n            } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n                \u003Cspan class=\"function\">reach_closed_end\u003C\u002Fspan>()\n            }\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"variable\">target\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">arrived\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">false\u003C\u002Fspan>\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">target\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n                \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;=\u003C\u002Fspan> \u003Cspan class=\"variable\">target\u003C\u002Fspan>) {\n                    \u003Cspan class=\"variable\">arrived\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">true\u003C\u002Fspan>\n                }\n                \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"variable\">target\u003C\u002Fspan>) {\n                    \u003Cspan class=\"variable\">arrived\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">true\u003C\u002Fspan>\n                }\n            }\n\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">arrived\u003C\u002Fspan>) {\n                \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">target\u003C\u002Fspan>\n            }\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">pos\u003C\u002Fspan>)\n            \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"stdlib\">math::round\u003C\u002Fspan>(\u003Cspan class=\"variable\">pos\u003C\u002Fspan>))\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_movement_ts\"\u003C\u002Fspan>, \u003Cspan class=\"stdlib\">time::uptime\u003C\u002Fspan>())\n\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">arrived\u003C\u002Fspan>) {\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n                \u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>)\n                \u003Cspan class=\"variable\">stop_needed\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target_stop_needed\"\u003C\u002Fspan>)\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target_stop_needed\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n                \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">stop_needed\u003C\u002Fspan>)) {\n                    \u003Cspan class=\"comment\">\u002F\u002F stop through a controller pulse;\u003C\u002Fspan>\n                    \u003Cspan class=\"comment\">\u002F\u002F the partial state is applied together with the stop pulse\u003C\u002Fspan>\n                    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">3\u003C\u002Fspan>)\n                    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n                        \u003Cspan class=\"function\">process_desired\u003C\u002Fspan>()\n                    }\n                } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n                    \u003Cspan class=\"comment\">\u002F\u002F direct stop, or the controller stops on its own (partial open mode)\u003C\u002Fspan>\n                    \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n                    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n                        \u003Cspan class=\"function\">direct_apply\u003C\u002Fspan>(\u003Cspan class=\"number\">0\u003C\u002Fspan>)\n                    }\n                    \u003Cspan class=\"function\">apply_stopped_state\u003C\u002Fspan>()\n                }\n            }\n        }\n    }\n\n    \u003Cspan class=\"comment\">\u002F\u002F keep ticking while there is anything to do\u003C\u002Fspan>\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"stdlib\">callback::set\u003C\u002Fspan>(\u003Cspan class=\"number\">99\u003C\u002Fspan>, \u003Cspan class=\"string\">\"onTick\"\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"tick_active\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">false\u003C\u002Fspan>)\n    }\n}\n\n\u003Cspan class=\"comment\">\u002F\u002F ---- limit switches ----\u003C\u002Fspan>\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"is_open\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">value\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F The sensor is authoritative (e.g. a remote may have driven the gate here),\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F so honor it - except for contact bounce in the instant after the gate leaves\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F the open limit: that shows up as a re-assert while closing and still within a\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F small position margin of the open limit.\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">bounce\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">&gt;\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"function\">sensor_bounce_margin\u003C\u002Fspan>()\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"operator\">!\u003C\u002Fspan>\u003Cspan class=\"variable\">bounce\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">reach_open_end\u003C\u002Fspan>()\n        }\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">&gt;=\u003C\u002Fspan> \u003Cspan class=\"number\">100\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F gate left the open limit without a command - assume external closing\u003C\u002Fspan>\n        \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        \u003Cspan class=\"function\">ensure_tick\u003C\u002Fspan>()\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"is_closed\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">value\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F The sensor is authoritative (e.g. a remote may have driven the gate here),\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F so honor it - except for contact bounce in the instant after the gate leaves\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F the closed limit: that shows up as a re-assert while opening and still within a\u003C\u002Fspan>\n        \u003Cspan class=\"comment\">\u002F\u002F small position margin of the closed limit.\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">bounce\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"function\">sensor_bounce_margin\u003C\u002Fspan>()\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"operator\">!\u003C\u002Fspan>\u003Cspan class=\"variable\">bounce\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">reach_closed_end\u003C\u002Fspan>()\n        }\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F gate left the closed limit without a command - assume external opening\u003C\u002Fspan>\n        \u003Cspan class=\"function\">set_dir\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        \u003Cspan class=\"function\">ensure_tick\u003C\u002Fspan>()\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"comment\">\u002F\u002F ---- safety inputs ----\u003C\u002Fspan>\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"prevent_open\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">value\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">value\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan>\u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"off\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">value\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"comment\">\u002F\u002F ---- command inputs - rising edge only ----\u003C\u002Fspan>\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">value\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"boolean\">false\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"off\"\u003C\u002Fspan>)) {\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"open\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_open\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"close\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>)) {\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"stop\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"toggle\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F forward directly as a hardware control pulse - the controller owns the cycle\u003C\u002Fspan>\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"comment\">\u002F\u002F a cycling controller channel owns the open\u002Fstop\u002Fclose sequence\u003C\u002Fspan>\n            \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"comment\">\u002F\u002F no cycling channel - reverse while moving, otherwise alternate direction\u003C\u002Fspan>\n        \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>)\n        \u003Cspan class=\"variable\">towards_close\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">false\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">towards_close\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">true\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n            \u003Cspan class=\"variable\">towards_close\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"boolean\">true\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">towards_close\u003C\u002Fspan>) {\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>)) {\n                \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n            }\n            \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n        } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_open\"\u003C\u002Fspan>)) {\n                \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n            }\n            \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n        }\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n    \u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"moving_dir\"\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">d\u003C\u002Fspan> \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"last_dir\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>)) {\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_open\"\u003C\u002Fspan>)) {\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">channel\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"string\">\"partial_open\"\u003C\u002Fspan>) {\n    \u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"control_mode\"\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">ppos\u003C\u002Fspan> \u003Cspan class=\"operator\">=\u003C\u002Fspan> \u003Cspan class=\"variable\">config\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_open_position\"\u003C\u002Fspan>)\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">2\u003C\u002Fspan>) {\n        \u003Cspan class=\"comment\">\u002F\u002F open\u002Fclose toggle controller cannot stop mid-travel\u003C\u002Fspan>\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">mode\u003C\u002Fspan> \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">3\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">math::abs\u003C\u002Fspan>(\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>) \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n            \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">4\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"comment\">\u002F\u002F dedicated partial open channel - the controller handles it\u003C\u002Fspan>\n            \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">4\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">or\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"is_closed\"\u003C\u002Fspan>)) {\n                \u003Cspan class=\"comment\">\u002F\u002F at closed position (by estimate or sensor);\u003C\u002Fspan>\n                \u003Cspan class=\"comment\">\u002F\u002F correct position estimate if sensor disagrees with it\u003C\u002Fspan>\n                \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&gt;\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan> \u003Cspan class=\"keyword\">and\u003C\u002Fspan> \u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"is_closed\"\u003C\u002Fspan>)) {\n                    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0.0\u003C\u002Fspan>)\n                    \u003Cspan class=\"stdlib\">output::set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"position\"\u003C\u002Fspan>, \u003Cspan class=\"number\">0\u003C\u002Fspan>)\n                }\n                \u003Cspan class=\"comment\">\u002F\u002F the PC pulse on a closed gate is interpreted as partial open\u003C\u002Fspan>\n                \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">4\u003C\u002Fspan>)\n            } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n            \u003Cspan class=\"comment\">\u002F\u002F close fully first; reach_closed_end will fire command(4) automatically\u003C\u002Fspan>\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>)) {\n                \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n            }\n            \u003Cspan class=\"function\">command\u003C\u002Fspan>(\u003Cspan class=\"number\">2\u003C\u002Fspan>) \u003Cspan class=\"comment\">\u002F\u002F clears all flags, so partial_after_close must be set afterwards\u003C\u002Fspan>\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_after_close\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n            }\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"function\">channel_with_function\u003C\u002Fspan>(\u003Cspan class=\"number\">3\u003C\u002Fspan>) \u003Cspan class=\"operator\">!=\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n            \u003Cspan class=\"comment\">\u002F\u002F stop at position using the open\u002Fstop\u002Fclose channel\u003C\u002Fspan>\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>) {\n                \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_open\"\u003C\u002Fspan>)) {\n                    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n                }\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">1\u003C\u002Fspan>)\n            } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n                \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>)) {\n                    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n                }\n                \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n            }\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n            \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target_stop_needed\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n            \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n                \u003Cspan class=\"function\">process_desired\u003C\u002Fspan>()\n            }\n            \u003Cspan class=\"function\">ensure_tick\u003C\u002Fspan>()\n        }\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">math::abs\u003C\u002Fspan>(\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">-\u003C\u002Fspan> \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>) \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"number\">1\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">set_gate_state\u003C\u002Fspan>(\u003Cspan class=\"number\">5\u003C\u002Fspan>)\n        \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n    }\n\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">pos\u003C\u002Fspan> \u003Cspan class=\"operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>) {\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_open\"\u003C\u002Fspan>)) {\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">1\u003C\u002Fspan>)\n    } \u003Cspan class=\"keyword\">else\u003C\u002Fspan> {\n        \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"stdlib\">input::get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"prevent_close\"\u003C\u002Fspan>)) {\n            \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n        }\n        \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"desired_action\"\u003C\u002Fspan>, \u003Cspan class=\"number\">2\u003C\u002Fspan>)\n    }\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"target\"\u003C\u002Fspan>, \u003Cspan class=\"variable\">ppos\u003C\u002Fspan>)\n    \u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">set\u003C\u002Fspan>(\u003Cspan class=\"string\">\"partial_pending\"\u003C\u002Fspan>, \u003Cspan class=\"boolean\">true\u003C\u002Fspan>)\n    \u003Cspan class=\"keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"variable\">state\u003C\u002Fspan>::\u003Cspan class=\"function\">get\u003C\u002Fspan>(\u003Cspan class=\"string\">\"pulse_phase\"\u003C\u002Fspan>) \u003Cspan class=\"operator\">==\u003C\u002Fspan> \u003Cspan class=\"number\">0\u003C\u002Fspan>) {\n        \u003Cspan class=\"function\">process_desired\u003C\u002Fspan>()\n    }\n    \u003Cspan class=\"function\">ensure_tick\u003C\u002Fspan>()\n    \u003Cspan class=\"keyword\">return\u003C\u002Fspan>\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003C\u002Fdetails>\n",[998,1000,1002,1005,1008],{"level":81,"text":724,"id":999},"inputs",{"level":81,"text":846,"id":1001},"outputs",{"level":81,"text":1003,"id":1004},"Konfiguracja","configuration",{"level":81,"text":1006,"id":1007},"Stan","state",{"level":81,"text":1009,"id":1010},"Kod źródłowy","source-code",{"block":1012,"labels":1079,"spec":1098},{"group":322,"id":367,"inputs":1013,"ioType":1054,"name":366,"outputs":1055},[1014,1018,1022,1026,1030,1034,1038,1042,1046,1050],{"abbrev":1015,"id":557,"name":1016,"type":1017},"T","Przełącz","BOOLEAN",{"abbrev":1019,"id":1020,"name":1021,"type":1017},"O","open","Otwórz",{"abbrev":1023,"id":1024,"name":1025,"type":1017},"C","close","Zamknij",{"abbrev":1027,"id":1028,"name":1029,"type":1017},"S","stop","Stop",{"abbrev":1031,"id":1032,"name":1033,"type":1017},"PO","partial_open","Uchyl",{"abbrev":1035,"id":1036,"name":1037,"type":1017},"IO","is_open","Otwarta",{"abbrev":1039,"id":1040,"name":1041,"type":1017},"IC","is_closed","Zamknięta",{"abbrev":1043,"id":1044,"name":1045,"type":1017},"SPO","prevent_open","Blokada otwierania",{"abbrev":1047,"id":1048,"name":1049,"type":1017},"SPC","prevent_close","Blokada zamykania",{"abbrev":1051,"id":1052,"name":1053,"type":1017},"OFF","off","Wyłącz",null,[1056,1060,1063,1066,1070,1075],{"abbrev":1057,"id":1058,"name":1059,"type":1017},"TG","control","Impuls sterujący",{"abbrev":1061,"id":1020,"name":1062,"type":1017},"OP","Otwieranie",{"abbrev":1064,"id":1024,"name":1065,"type":1017},"CL","Zamykanie",{"abbrev":1067,"id":1068,"name":1069,"type":1017},"M","moving","W ruchu",{"abbrev":1071,"id":1072,"name":1073,"type":1074},"P","position","Pozycja","NUMBER",{"abbrev":1076,"id":1077,"name":1078,"type":1074},"GS","gate_state","Stan bramy",{"config":1080,"detail":1088,"port":1093,"sections":1095,"state":1097},{"default":1081,"description":1082,"details":1083,"id":1084,"name":1085,"type":1086,"unit":1087},"Domyślnie","Opis","Szczegóły","ID","Nazwa","Typ","Jednostka",{"required":1089,"subtype":1090,"values":1091,"visible_when":1092},"Wymagane","Podtyp","Wartości","Widoczne gdy",{"abbrev":1094,"default":1081,"description":1082,"id":1084,"name":1085,"type":1086},"Skrót",{"configuration":1003,"inputs":724,"outputs":846,"source_code":1009,"state":1006,"view_source":1096},"Pokaż kod Volang",{"default":1081,"description":1082,"id":1084,"name":1085,"type":1086,"unit":1087},{"config":1099,"inputs":1210,"outputs":1232,"state":1245},[1100,1115,1125,1136,1143,1156,1170,1179,1189,1198,1205],{"default":1101,"description":1102,"details":1103,"id":1111,"name":1112,"type":1113,"unit":1114},"0","Typ bramy, używany do właściwej animacji w aplikacjach klienckich: Brama garażowa, Brama (lewe skrzydło), Brama (prawe skrzydło), Brama dwuskrzydłowa, Brama przesuwna (w lewo), Brama przesuwna (w prawo)",{"enumValues":1104},[1105,1106,1107,1108,1109,1110],"Garage door","Gate (left wing)","Gate (right wing)","Double wing gate","Sliding gate (left)","Sliding gate (right)","gate_type","Typ bramy","ENUM","",{"default":1101,"description":1116,"details":1117,"id":1123,"name":1124,"type":1113,"unit":1114},"Sposób sterowania bramą: bezpośredni (sygnały poziomu), pojedyncze wyjście impulsowe otwórz\u002Fstop\u002Fzamknij (3F), pojedyncze wyjście impulsowe otwórz\u002Fzamknij, lub oddzielne impulsy otwierania i zamykania.",{"enumValues":1118},[1119,1120,1121,1122],"Direct motor control","Single control: open\u002Fstop\u002Fclose","Single control: open\u002Fclose","Separate open and close pulses","control_mode","Tryb sterowania",{"default":1126,"description":1127,"details":1128,"id":1133,"name":1134,"type":1074,"unit":1135},"30","Czas potrzebny do pełnego otwarcia bramy, w sekundach. Używany do symulacji pozycji bramy.",{"rules":1129},[1130],{"kind":1131,"op":1132,"value":69},"compare",">","opening_duration","Czas otwierania","s",{"default":1126,"description":1137,"details":1138,"id":1141,"name":1142,"type":1074,"unit":1135},"Czas potrzebny do pełnego zamknięcia bramy, w sekundach. Używany do symulacji pozycji bramy.",{"rules":1139},[1140],{"kind":1131,"op":1132,"value":69},"closing_duration","Czas zamykania",{"default":1144,"description":1145,"details":1146,"id":1153,"name":1154,"type":1074,"unit":1155},"20","Pozycja docelowa polecenia uchylenia, jako procent pełnego otwarcia (0-100)",{"rules":1147},[1148,1150],{"kind":1131,"op":1149,"value":69},"≥",{"kind":1131,"op":1151,"value":1152},"≤",100,"partial_open_position","Pozycja uchylenia","%",{"default":1101,"description":1157,"details":1158,"id":1168,"name":1169,"type":1113,"unit":1114},"Funkcja sterownika podłączona do wyjścia impulsu otwierania: Otwórz (Ot), Zamknij (ZA), Otwórz\u002FZamknij (OZ), Otwórz\u002FStop\u002FZamknij (3F), Uchyl (U), Uchyl\u002FZamknij (PC)",{"enumValues":1159,"visibleWhen":1166},[1160,1161,1162,1163,1164,1165],"Open","Close","Open\u002FClose","Open\u002FStop\u002FClose","Partial open","Partial open\u002FClose",{"configId":1123,"values":1167},[1122],"open_output_function","Funkcja wyjścia otwierania",{"default":1171,"description":1172,"details":1173,"id":1177,"name":1178,"type":1113,"unit":1114},"1","Funkcja sterownika podłączona do wyjścia impulsu zamykania: Otwórz (Ot), Zamknij (ZA), Otwórz\u002FZamknij (OZ), Otwórz\u002FStop\u002FZamknij (3F), Uchyl (U), Uchyl\u002FZamknij (PC)",{"enumValues":1174,"visibleWhen":1175},[1160,1161,1162,1163,1164,1165],{"configId":1123,"values":1176},[1122],"close_output_function","Funkcja wyjścia zamykania",{"default":1180,"description":1181,"details":1182,"id":1187,"name":1188,"type":1074,"unit":1135},"0.5","Czas trwania impulsów na wyjściach sterujących, otwierania i zamykania, w sekundach",{"rules":1183,"visibleWhen":1185},[1184],{"kind":1131,"op":1132,"value":69},{"configId":1123,"values":1186},[1120,1121,1122],"pulse_duration","Czas trwania impulsu",{"default":1180,"description":1190,"details":1191,"id":1196,"name":1197,"type":1074,"unit":1135},"Minimalna przerwa między dwoma kolejnymi impulsami, w sekundach",{"rules":1192,"visibleWhen":1194},[1193],{"kind":1131,"op":1149,"value":69},{"configId":1123,"values":1195},[1120,1121,1122],"pulse_pause","Przerwa między impulsami",{"default":1180,"description":1199,"details":1200,"id":1203,"name":1204,"type":1074,"unit":1135},"Czas potrzebny silnikowi na zmianę kierunku, w sekundach. W trybie bezpośrednim chroni silnik, a w pozostałych trybach utrzymuje dokładność szacowanej pozycji.",{"rules":1201},[1202],{"kind":1131,"op":1149,"value":69},"motor_lock_duration","Czas blokady silnika",{"default":1206,"description":1207,"details":1054,"id":1208,"name":1209,"type":1017,"unit":1114},"true","Gdy włączone, wejścia is_open i is_closed są wiodącym źródłem informacji o pozycji krańcowej. Pozycja jest nadal szacowana z czasów konfiguracji na potrzeby wyświetlania. Wyłącz, gdy brak podłączonych czujników.","use_sensors","Używaj czujników krańcowych",[1211,1214,1216,1218,1220,1222,1224,1226,1228,1230],{"abbrev":1015,"default":1212,"description":1213,"id":557,"name":1016,"type":1017},"false","Sterowanie jednym przyciskiem. Przy sterowaniu bezpośrednim lub oddzielnych impulsach przełącza cyklicznie: otwórz, stop, zamknij, stop. Przy pojedynczym wyjściu sterującym impuls jest przekazywany do sterownika, który sam zarządza cyklem.",{"abbrev":1019,"default":1212,"description":1215,"id":1020,"name":1021,"type":1017},"Całkowicie otwiera bramę",{"abbrev":1023,"default":1212,"description":1217,"id":1024,"name":1025,"type":1017},"Całkowicie zamyka bramę",{"abbrev":1027,"default":1212,"description":1219,"id":1028,"name":1029,"type":1017},"Zatrzymuje ruch. Dostępne przy sterowaniu bezpośrednim i trybie sterownika otwórz\u002Fstop\u002Fzamknij; ignorowane w trybach sterownika bez funkcji stop.",{"abbrev":1031,"default":1212,"description":1221,"id":1032,"name":1033,"type":1017},"Przesuwa bramę do pozycji częściowego otwarcia (np. furtka lub wietrzenie), zgodnie ze skonfigurowanym trybem uchylania",{"abbrev":1035,"default":1212,"description":1223,"id":1036,"name":1037,"type":1017},"Wyłącznik krańcowy zgłaszający pozycję pełnego otwarcia. Koryguje symulowaną pozycję i wykrywa ruch wywołany zewnętrznie.",{"abbrev":1039,"default":1212,"description":1225,"id":1040,"name":1041,"type":1017},"Wyłącznik krańcowy zgłaszający pozycję pełnego zamknięcia. Koryguje symulowaną pozycję i wykrywa ruch wywołany zewnętrznie.",{"abbrev":1043,"default":1212,"description":1227,"id":1044,"name":1045,"type":1017},"Wejście czujnika bezpieczeństwa. Gdy aktywne, otwieranie jest zablokowane; trwający ruch otwierania jest zatrzymywany, jeśli tryb sterowania pozwala na zatrzymanie.",{"abbrev":1047,"default":1212,"description":1229,"id":1048,"name":1049,"type":1017},"Wejście czujnika bezpieczeństwa, np. fotokomórki. Gdy aktywne, zamykanie jest zablokowane; trwający ruch zamykania jest zatrzymywany, jeśli tryb sterowania pozwala na zatrzymanie.",{"abbrev":1051,"default":1212,"description":1231,"id":1052,"name":1053,"type":1017},"Zatrzymuje bramę przy aktywacji i blokuje wszystkie polecenia, gdy aktywne",[1233,1235,1237,1239,1241,1243],{"abbrev":1057,"default":1212,"description":1234,"id":1058,"name":1059,"type":1017},"Wyjście impulsowe dla sterowników z pojedynczym wejściem sterującym (cykl otwórz\u002Fstop\u002Fzamknij lub otwórz\u002Fzamknij)",{"abbrev":1061,"default":1212,"description":1236,"id":1020,"name":1062,"type":1017},"Przy sterowaniu bezpośrednim: sygnał poziomu sterujący silnikiem w kierunku otwierania. Przy oddzielnych impulsach: impuls otwarcia dla sterownika.",{"abbrev":1064,"default":1212,"description":1238,"id":1024,"name":1065,"type":1017},"Przy sterowaniu bezpośrednim: sygnał poziomu sterujący silnikiem w kierunku zamykania. Przy oddzielnych impulsach: impuls zamknięcia dla sterownika.",{"abbrev":1067,"default":1212,"description":1240,"id":1068,"name":1069,"type":1017},"Aktywne podczas ruchu bramy",{"abbrev":1071,"default":1101,"description":1242,"id":1072,"name":1073,"type":1074},"Bieżąca pozycja bramy jako procent (0=zamknięta, 100=otwarta)",{"abbrev":1076,"default":1101,"description":1244,"id":1077,"name":1078,"type":1074},"Bieżący stan bramy: 0=zamknięta, 1=otwieranie, 2=otwarta, 3=zamykanie, 4=zatrzymana w trakcie, 5=uchylona",[1246,1249,1253,1258,1262,1266,1270,1274,1278,1282,1286,1290,1294,1298,1302,1306,1310],{"default":1247,"description":1248,"id":1072,"name":1073,"type":1074,"unit":1155},"0.0","Surowa wartość symulowanej pozycji bramy jako procent (0-100)",{"default":1101,"description":1250,"id":1251,"name":1252,"type":1074,"unit":1114},"Bieżący kierunek ruchu: 0=zatrzymana, 1=otwieranie, -1=zamykanie","moving_dir","Kierunek ruchu",{"default":1254,"description":1255,"id":1256,"name":1257,"type":1074,"unit":1114},"-1","Kierunek ostatniego ruchu: 1=otwieranie, -1=zamykanie","last_dir","Ostatni kierunek",{"default":1254,"description":1259,"id":1260,"name":1261,"type":1074,"unit":1155},"Pozycja docelowa bieżącego ruchu jako procent lub -1 przy ruchu do pozycji krańcowej","target","Pozycja docelowa",{"default":1212,"description":1263,"id":1264,"name":1265,"type":1017,"unit":1114},"Wskazuje, że bieżący ruch został rozpoczęty poleceniem uchylenia","partial_pending","Oczekujące uchylenie",{"default":1101,"description":1267,"id":1268,"name":1269,"type":1074,"unit":1114},"Oczekująca akcja do wykonania: 0=brak, 1=otwórz, 2=zamknij, 3=stop, 4=uchylenie przez sterownik, 5=surowy impuls sterujący","desired_action","Żądana akcja",{"default":1101,"description":1271,"id":1272,"name":1273,"type":1074,"unit":1114},"Śledzi cykl otwórz\u002Fstop\u002Fzamknij\u002Fstop sterownika za wyjściem sterującym: akcja wywołana następnym impulsem (0=otwórz, 1=stop, 2=zamknij, 3=stop)","cycle_next","Pozycja cyklu sterownika",{"default":1101,"description":1275,"id":1276,"name":1277,"type":1074,"unit":1114},"Śledzi cykl otwórz\u002Fstop\u002Fzamknij\u002Fstop kanału sterownika za wyjściem impulsu otwierania","cycle_next_op","Pozycja cyklu (wyjście otwierania)",{"default":1101,"description":1279,"id":1280,"name":1281,"type":1074,"unit":1114},"Śledzi cykl otwórz\u002Fstop\u002Fzamknij\u002Fstop kanału sterownika za wyjściem impulsu zamykania","cycle_next_cl","Pozycja cyklu (wyjście zamykania)",{"default":1212,"description":1283,"id":1284,"name":1285,"type":1017,"unit":1114},"Wskazuje, że osiągnięcie pozycji docelowej wymaga wysłania impulsu stop do sterownika","target_stop_needed","Wymagany stop na pozycji docelowej",{"default":1212,"description":1287,"id":1288,"name":1289,"type":1017,"unit":1114},"Wskazuje, że polecenie uchylenia oczekuje na pełne zamknięcie bramy przed wysłaniem impulsu do sterownika","partial_after_close","Uchylenie oczekuje na zamknięcie",{"default":1101,"description":1291,"id":1292,"name":1293,"type":1074,"unit":1114},"Wyjście aktualnie emitujące impuls: 0=brak, 1=sterujące, 2=otwieranie, 3=zamykanie","pulse_out","Aktywne wyjście impulsowe",{"default":1101,"description":1295,"id":1296,"name":1297,"type":1074,"unit":1114},"Faza mechanizmu impulsów: 0=bezczynny, 1=impuls aktywny, 2=przerwa lub oczekiwanie blokady silnika","pulse_phase","Faza impulsu",{"default":1101,"description":1299,"id":1300,"name":1301,"type":1074,"unit":1114},"Liczba taktów pozostałych w bieżącej fazie impulsu","pulse_ticks","Pozostałe takty impulsu",{"default":1101,"description":1303,"id":1304,"name":1305,"type":1074,"unit":1114},"Liczba taktów, przez które szacowana pozycja jest wstrzymana po zmianie kierunku, gdy trwa blokada silnika (tryby pośrednie)","move_lock_ticks","Takty blokady ruchu",{"default":1212,"description":1307,"id":1308,"name":1309,"type":1017,"unit":1114},"Wskazuje, czy okresowe wywołanie symulacji jest zaplanowane","tick_active","Aktywny takt",{"default":1311,"description":1312,"id":1313,"name":1314,"type":1074,"unit":1315},"-60000","Znacznik czasu ostatniego ruchu, używany do pauzy blokady silnika przy zmianie kierunku","last_movement_ts","Znacznik czasu ostatniego ruchu","milliseconds",1781697074429]