#pragma once #include namespace Scan { constexpr uint8_t MIN_ANGLE=30, MAX_ANGLE=150, STEP=4, BINS=31; constexpr uint32_t TIMEOUT_US=26000, SHOT_GAP_MS=65; inline bool elapsed(uint32_t now,uint32_t then,uint32_t interval){return uint32_t(now-then)>=interval;} inline uint16_t cmFromPulse(uint32_t us){ // Approximate sound speed at room temperature; round to whole centimetres. if(us<116 || us>11662)return 0; // 2..200 cm operating window return uint16_t((us*343UL+10000UL)/20000UL); } struct Filtered {uint16_t cm,spread;uint8_t valid;}; inline Filtered filter(const uint16_t raw[3]){ uint16_t a[3];uint8_t n=0; for(uint8_t i=0;i<3;i++)if(raw[i]>=2&&raw[i]<=200)a[n++]=raw[i]; for(uint8_t i=0;i0)||(bin==0&&direction<0)){direction=-direction;passes++;} bin=uint8_t(int16_t(bin)+direction); } }; struct Proximity { bool near=false; void update(uint16_t cm,uint16_t threshold){ if(!cm){near=false;return;} // unknown is never displayed as an old near/far result if(cm=threshold+5)near=false; } }; struct Button { bool raw=false,stable=false;uint32_t changed=0; bool update(bool pressed,uint32_t now){ if(pressed!=raw){raw=pressed;changed=now;} if(raw!=stable&&elapsed(now,changed,30)){stable=raw;return stable;} return false; } }; }