[{"data":1,"prerenderedAt":1312},["ShallowReactive",2],{"manifest":3,"hreflang-alternates":990,"doc-en-logic-blocks\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":1013},"Learn how the Gate logic block works, when to use it, and how to configure it in your Voldeno smart home automation.",[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\">Process\u003C\u002Fspan>\n\u003C\u002Fdiv>\n\n\u003Cp class=\"block-description\">Controls gates and garage doors, either directly or through an external gate controller\u003C\u002Fp>\n\u003C!-- BLOCK_DIAGRAM -->\n\u003Ch2 id=\"source-code\">\u003Ca href=\"#source-code\" class=\"anchor\">#\u003C\u002Fa> Source Code\u003C\u002Fh2>\n\u003Cdetails class=\"code-details\">\u003Csummary>View Volang source\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,1001,1004,1007,1010],{"level":81,"text":999,"id":1000},"Inputs","inputs",{"level":81,"text":1002,"id":1003},"Outputs","outputs",{"level":81,"text":1005,"id":1006},"Configuration","configuration",{"level":81,"text":1008,"id":1009},"State","state",{"level":81,"text":1011,"id":1012},"Source Code","source-code",{"block":1014,"labels":1078,"spec":1097},{"group":322,"id":367,"inputs":1015,"ioType":1055,"name":366,"outputs":1056},[1016,1019,1023,1027,1031,1035,1039,1043,1047,1051],{"abbrev":1017,"id":557,"name":556,"type":1018},"T","BOOLEAN",{"abbrev":1020,"id":1021,"name":1022,"type":1018},"O","open","Open",{"abbrev":1024,"id":1025,"name":1026,"type":1018},"C","close","Close",{"abbrev":1028,"id":1029,"name":1030,"type":1018},"S","stop","Stop",{"abbrev":1032,"id":1033,"name":1034,"type":1018},"PO","partial_open","Partial open",{"abbrev":1036,"id":1037,"name":1038,"type":1018},"IO","is_open","Is open",{"abbrev":1040,"id":1041,"name":1042,"type":1018},"IC","is_closed","Is closed",{"abbrev":1044,"id":1045,"name":1046,"type":1018},"SPO","prevent_open","Prevent opening",{"abbrev":1048,"id":1049,"name":1050,"type":1018},"SPC","prevent_close","Prevent closing",{"abbrev":1052,"id":1053,"name":1054,"type":1018},"OFF","off","Off",null,[1057,1061,1063,1065,1069,1074],{"abbrev":1058,"id":1059,"name":1060,"type":1018},"TG","control","Control pulse",{"abbrev":1062,"id":1021,"name":1022,"type":1018},"OP",{"abbrev":1064,"id":1025,"name":1026,"type":1018},"CL",{"abbrev":1066,"id":1067,"name":1068,"type":1018},"M","moving","In motion",{"abbrev":1070,"id":1071,"name":1072,"type":1073},"P","position","Position","NUMBER",{"abbrev":1075,"id":1076,"name":1077,"type":1073},"GS","gate_state","Gate state",{"config":1079,"detail":1087,"port":1092,"sections":1094,"state":1096},{"default":1080,"description":1081,"details":1082,"id":1083,"name":1084,"type":1085,"unit":1086},"Default","Description","Details","ID","Name","Type","Unit",{"required":1088,"subtype":1089,"values":1090,"visible_when":1091},"Required","Subtype","Values","Visible when",{"abbrev":1093,"default":1080,"description":1081,"id":1083,"name":1084,"type":1085},"Abbrev",{"configuration":1005,"inputs":999,"outputs":1002,"source_code":1011,"state":1008,"view_source":1095},"View Volang source",{"default":1080,"description":1081,"id":1083,"name":1084,"type":1085,"unit":1086},{"config":1098,"inputs":1206,"outputs":1228,"state":1241},[1099,1114,1124,1135,1142,1155,1166,1175,1185,1194,1201],{"default":1100,"description":1101,"details":1102,"id":1110,"name":1111,"type":1112,"unit":1113},"0","Type of the gate, used for the proper animation in client applications: Garage door, Gate (left wing), Gate (right wing), Double wing gate, Sliding gate (left), Sliding gate (right)",{"enumValues":1103},[1104,1105,1106,1107,1108,1109],"Garage door","Gate (left wing)","Gate (right wing)","Double wing gate","Sliding gate (left)","Sliding gate (right)","gate_type","Gate type","ENUM","",{"default":1100,"description":1115,"details":1116,"id":1122,"name":1123,"type":1112,"unit":1113},"How the gate is driven: direct motor control (level signals), single pulse output open\u002Fstop\u002Fclose (3F cycle), single pulse output open\u002Fclose toggle, or separate open and close pulse outputs.",{"enumValues":1117},[1118,1119,1120,1121],"Direct motor control","Single control: open\u002Fstop\u002Fclose","Single control: open\u002Fclose","Separate open and close pulses","control_mode","Control mode",{"default":1125,"description":1126,"details":1127,"id":1132,"name":1133,"type":1073,"unit":1134},"30","The time taken to fully open the gate, in seconds. Used to simulate the gate position.",{"rules":1128},[1129],{"kind":1130,"op":1131,"value":69},"compare",">","opening_duration","Opening duration","s",{"default":1125,"description":1136,"details":1137,"id":1140,"name":1141,"type":1073,"unit":1134},"The time taken to fully close the gate, in seconds. Used to simulate the gate position.",{"rules":1138},[1139],{"kind":1130,"op":1131,"value":69},"closing_duration","Closing duration",{"default":1143,"description":1144,"details":1145,"id":1152,"name":1153,"type":1073,"unit":1154},"20","Target position for the partial open command, as a percentage of fully open (0-100)",{"rules":1146},[1147,1149],{"kind":1130,"op":1148,"value":69},"≥",{"kind":1130,"op":1150,"value":1151},"≤",100,"partial_open_position","Partial open position","%",{"default":1100,"description":1156,"details":1157,"id":1164,"name":1165,"type":1112,"unit":1113},"Controller function wired to the open pulse output: Open (Ot), Close (ZA), Open\u002FClose (OZ), Open\u002FStop\u002FClose (3F), Partial open (U), Partial open\u002FClose (PC)",{"enumValues":1158,"visibleWhen":1162},[1022,1026,1159,1160,1034,1161],"Open\u002FClose","Open\u002FStop\u002FClose","Partial open\u002FClose",{"configId":1122,"values":1163},[1121],"open_output_function","Open output function",{"default":1167,"description":1168,"details":1169,"id":1173,"name":1174,"type":1112,"unit":1113},"1","Controller function wired to the close pulse output: Open (Ot), Close (ZA), Open\u002FClose (OZ), Open\u002FStop\u002FClose (3F), Partial open (U), Partial open\u002FClose (PC)",{"enumValues":1170,"visibleWhen":1171},[1022,1026,1159,1160,1034,1161],{"configId":1122,"values":1172},[1121],"close_output_function","Close output function",{"default":1176,"description":1177,"details":1178,"id":1183,"name":1184,"type":1073,"unit":1134},"0.5","Duration of pulses on the control, open and close outputs, in seconds",{"rules":1179,"visibleWhen":1181},[1180],{"kind":1130,"op":1131,"value":69},{"configId":1122,"values":1182},[1119,1120,1121],"pulse_duration","Pulse duration",{"default":1176,"description":1186,"details":1187,"id":1192,"name":1193,"type":1073,"unit":1134},"Minimal pause between two consecutive pulses, in seconds",{"rules":1188,"visibleWhen":1190},[1189],{"kind":1130,"op":1148,"value":69},{"configId":1122,"values":1191},[1119,1120,1121],"pulse_pause","Pulse pause",{"default":1176,"description":1195,"details":1196,"id":1199,"name":1200,"type":1073,"unit":1134},"Time the motor needs to reverse direction, in seconds. Protects the motor in direct mode and keeps the estimated position accurate in the other modes.",{"rules":1197},[1198],{"kind":1130,"op":1148,"value":69},"motor_lock_duration","Motor lock duration",{"default":1202,"description":1203,"details":1055,"id":1204,"name":1205,"type":1018,"unit":1113},"true","When enabled, the is_open and is_closed inputs are the authoritative source for end-of-travel events. Position is still estimated from configured durations for display. Requires sensors to be connected; disable when no sensors are used.","use_sensors","Use limit switch sensors",[1207,1210,1212,1214,1216,1218,1220,1222,1224,1226],{"abbrev":1017,"default":1208,"description":1209,"id":557,"name":556,"type":1018},"false","Single button control. With direct motor control or separate pulses it cycles open, stop, close, stop. With a single control output the pulse is forwarded to the controller which owns the cycle.",{"abbrev":1020,"default":1208,"description":1211,"id":1021,"name":1022,"type":1018},"Fully opens the gate",{"abbrev":1024,"default":1208,"description":1213,"id":1025,"name":1026,"type":1018},"Fully closes the gate",{"abbrev":1028,"default":1208,"description":1215,"id":1029,"name":1030,"type":1018},"Stops the movement. Available with direct motor control and the open\u002Fstop\u002Fclose controller mode; ignored in controller modes without a stop function.",{"abbrev":1032,"default":1208,"description":1217,"id":1033,"name":1034,"type":1018},"Moves the gate to the partial open position (e.g. pedestrian or ventilation position), according to the configured partial open mode",{"abbrev":1036,"default":1208,"description":1219,"id":1037,"name":1038,"type":1018},"Limit switch reporting the fully open position. Corrects the simulated position and detects externally triggered movement.",{"abbrev":1040,"default":1208,"description":1221,"id":1041,"name":1042,"type":1018},"Limit switch reporting the fully closed position. Corrects the simulated position and detects externally triggered movement.",{"abbrev":1044,"default":1208,"description":1223,"id":1045,"name":1046,"type":1018},"Safety sensor input. While active, opening is blocked; an ongoing opening movement is stopped if the control mode allows stopping.",{"abbrev":1048,"default":1208,"description":1225,"id":1049,"name":1050,"type":1018},"Safety sensor input, e.g. a photocell. While active, closing is blocked; an ongoing closing movement is stopped if the control mode allows stopping.",{"abbrev":1052,"default":1208,"description":1227,"id":1053,"name":1054,"type":1018},"Stops the gate when activated and blocks all commands while active",[1229,1231,1233,1235,1237,1239],{"abbrev":1058,"default":1208,"description":1230,"id":1059,"name":1060,"type":1018},"Pulse output for single control input controllers (open\u002Fstop\u002Fclose or open\u002Fclose cycle)",{"abbrev":1062,"default":1208,"description":1232,"id":1021,"name":1022,"type":1018},"With direct motor control: level signal driving the motor in the opening direction. With separate pulses: open pulse for the controller.",{"abbrev":1064,"default":1208,"description":1234,"id":1025,"name":1026,"type":1018},"With direct motor control: level signal driving the motor in the closing direction. With separate pulses: close pulse for the controller.",{"abbrev":1066,"default":1208,"description":1236,"id":1067,"name":1068,"type":1018},"Active while the gate is moving",{"abbrev":1070,"default":1100,"description":1238,"id":1071,"name":1072,"type":1073},"Current gate position as a percentage (0=fully closed, 100=fully open)",{"abbrev":1075,"default":1100,"description":1240,"id":1076,"name":1077,"type":1073},"Current gate state: 0=closed, 1=opening, 2=open, 3=closing, 4=stopped midway, 5=partially open",[1242,1245,1249,1254,1258,1262,1266,1270,1274,1278,1282,1286,1290,1294,1298,1302,1306],{"default":1243,"description":1244,"id":1071,"name":1072,"type":1073,"unit":1154},"0.0","Raw value of the simulated gate position as a percentage (0-100), not rounded",{"default":1100,"description":1246,"id":1247,"name":1248,"type":1073,"unit":1113},"Current movement direction: 0=stopped, 1=opening, -1=closing","moving_dir","Moving direction",{"default":1250,"description":1251,"id":1252,"name":1253,"type":1073,"unit":1113},"-1","Direction of the last movement: 1=opening, -1=closing","last_dir","Last direction",{"default":1250,"description":1255,"id":1256,"name":1257,"type":1073,"unit":1154},"Target position for the current movement as a percentage, or -1 when moving to an end position","target","Target position",{"default":1208,"description":1259,"id":1260,"name":1261,"type":1018,"unit":1113},"Indicates that the current movement was started by a partial open command","partial_pending","Partial open pending",{"default":1100,"description":1263,"id":1264,"name":1265,"type":1073,"unit":1113},"Pending action to perform: 0=none, 1=open, 2=close, 3=stop, 4=partial open via controller, 5=raw control pulse","desired_action","Desired action",{"default":1100,"description":1267,"id":1268,"name":1269,"type":1073,"unit":1113},"Tracks the open\u002Fstop\u002Fclose\u002Fstop cycle of an external controller behind the control output: action the next pulse will trigger (0=open, 1=stop, 2=close, 3=stop)","cycle_next","Controller cycle position",{"default":1100,"description":1271,"id":1272,"name":1273,"type":1073,"unit":1113},"Tracks the open\u002Fstop\u002Fclose\u002Fstop cycle of a controller channel behind the open pulse output","cycle_next_op","Controller cycle position (open output)",{"default":1100,"description":1275,"id":1276,"name":1277,"type":1073,"unit":1113},"Tracks the open\u002Fstop\u002Fclose\u002Fstop cycle of a controller channel behind the close pulse output","cycle_next_cl","Controller cycle position (close output)",{"default":1208,"description":1279,"id":1280,"name":1281,"type":1018,"unit":1113},"Indicates that reaching the target position requires sending a stop pulse to the controller","target_stop_needed","Stop needed at target",{"default":1208,"description":1283,"id":1284,"name":1285,"type":1018,"unit":1113},"Indicates that a partial open command is waiting for the gate to reach fully closed before issuing the controller pulse","partial_after_close","Partial open pending after close",{"default":1100,"description":1287,"id":1288,"name":1289,"type":1073,"unit":1113},"Output currently emitting a pulse: 0=none, 1=control, 2=open, 3=close","pulse_out","Active pulse output",{"default":1100,"description":1291,"id":1292,"name":1293,"type":1073,"unit":1113},"Phase of the pulse machinery: 0=idle, 1=pulse high, 2=pause or motor lock wait","pulse_phase","Pulse phase",{"default":1100,"description":1295,"id":1296,"name":1297,"type":1073,"unit":1113},"Ticks remaining in the current pulse phase","pulse_ticks","Pulse ticks",{"default":1100,"description":1299,"id":1300,"name":1301,"type":1073,"unit":1113},"Ticks the simulated position is held after a reversal while the motor lock elapses (non-direct modes)","move_lock_ticks","Movement lock ticks",{"default":1208,"description":1303,"id":1304,"name":1305,"type":1018,"unit":1113},"Indicates whether the periodic simulation callback is scheduled","tick_active","Tick active",{"default":1307,"description":1308,"id":1309,"name":1310,"type":1073,"unit":1311},"-60000","Timestamp of the last movement, used for the motor lock pause on direction change","last_movement_ts","Last movement timestamp","milliseconds",1781697084902]