diff --git a/function-diagram.drawio b/function-diagram.drawio
index b3835c3..6062a78 100644
--- a/function-diagram.drawio
+++ b/function-diagram.drawio
@@ -1 +1 @@
-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
\ No newline at end of file
+7R3ZctrI9lvuA1WeW2VK+/LoeIk949gZ24mT++ISIEATITFCeMnX3+6WWkjdR0KANmNSSWxEI1qnz7725NPZ6+fAmk+/+CPb7UnC6LUnn/UkSZQUA/3AV96iK4asRhcmgTOKF60u3Du/7egiXbV0RvYisy70fTd05tmLQ9/z7GGYuWYFgf+SXTb23eyXzq2JzV24H1ouf/XRGYXT+Kqomas3Lm1nMqVfralK9M7MoquF6MJiao38l9Ql+bwnnwa+H0a/zV5PbRcDj8Il+txFzrvJzgLbC8t84E/f/GZr0+t/w79MWX04n8w//XUsxrt9ttxl/MhX3nwZxlsO3yggFi/OzLU89OrTIrSCMD4pSUYX+J3Em3u2g9B+TV2Kd/bZ9md2GLyhJfG7mhJDKUYTiiUvK6BLQrxkmoJ3ctGKD3qS3HoFCvRLDI1NIKNykDlGLz8tw9D30C/3GAo9SXPRTj4NAvTbBP+WWXNnL+x1a+7zVnz1QwRPBz+OHfBLcj4URF8piMcyd4boLPC6aThDkDgT0a+W60w89Ltrj/E7+LwchPwn8eWZMxrhD39Cd3V+WwNyIwG9nvuOFxKIq5966hm+0zL0FxFOiARHAv+Xfeq7foCueD5BnLHjuswlHnWK0bQ0QolyFp8EDp9ECJ/M2tBJ49Dpdhm2QGmGwVCa3m+f1nSQ1qRX9J+BhYczcTBS68cLezLDz46vLeau9QaTwWD5+3d5ovl+cZa/dDG3vMwBaf8uMcv+9DJ1QvsYvT1E10/wsQQRRtMFqTv1JNlM3RMBKbrtag+IrCSB/CK1vpeLx/bhcXf+vezxnfoe4jYYyVxrNt8nrqdtStwM1xMNnuvpKk/ZoqLuTtnG7wv7ZhSMX9wb91G4dn9/fUWPwBH2hW2FSwRZdLurkY2+MEL7a2cRErSBTnjhIsUJkbz/glHvZWrjH0PXX9hEH8T/WcEkT5AuQn+++piHl8/8ZzvmI4E99CceOsMR/OmZ5S0tlyxE50C+cRgjnHyBXtj9SR/9WHovjjfCIJxYjlcCCcviyhpkxc8W0959RHpnL0gTx9jrL72RPYpxtwLJIcqmmkUvyQREhw6IDlGqAMHOzcngq/L849+fyq3y2z/7fhreH+PPMxiWqFbWEKlP3qJ3KvVOMHs9ig+uP5zP/yiSu641sN1P1vDXhACRPSR0F3oJMTKB/KkIxCIDYV3iIayLJg9hTa4AwiAXkgwOwvePT3fn9+cPfaSghDYHyWDqzwbLRQ5epmiAh1jxGZeHo5RVckQR0P8kAFH1ulQcyeSgiG+I/wqu7U3C6Q3hceQtrGixvMj2hsi4Dp6Ign/Eo++K3MUOAV5SSgJeqwvwVPNPAT4MljzS2iNk+Mcv/SCc+hPfs9zz1VWGoa7WXPuYBxO4/mOH4VussGPdIAt1+9UJf+CPI407evUz9c7Za3xn8uItl28XntTCXwZDuwQ1xwJzPcJiuBSefGC7Vug8Zx0m1R8jr0lQU3eIzoWYyAjJEI7hHUVvDGJBULksHtrkCwtUx/UCGZAiFxf5sgctuSB/mqRerSTxyhUQL/gIgBMGyZ4uSx5ZSezpNmQPDEXe9/DsuyF2fVKBY42GSLJYo6PJ3PGf5n7o/MGLoEhOPcSqdvzJ1Z3+S6DQTbkks3IJcDCCplEVcgk+FN7z+kHkUiGlp+VSITI3L5fg7fCuq1gqLZHdOUuZprGah23FheNNMPSyHl7BIgbkQXZtSeFZtgvJLg0g8PpkF6/xI9n1lRhOYmfllyEx4kuBxJfSpPiSeA0elEQYDzsqfgyxz6CnqgACSEmAnwasUhuG8pb9hxZBZkkRRBGyIyJI4k2jSIbMqSGUSB7xIFBK06ye1RhlvW2BIsn5AkXqrECRmMh+B+QJr3mD8kTtrjyRZKOvd0+gSLy5/pEFCiXY9QJF6ZZA4f0FeQJF4s72IFByiVaSWaLtgFDh7ddEqMidFSqyyYGyA3KFV6dBuSIK3RUsssnaf52QK7wp/aHlil5WrhidkitAKC5PrpRJXjzIlZhmuYy+BoWK9XCrv3nftZ+Ce3L56n89ub0JjxWevXWUNNFZBG+pD+GXP9PvrT5GXlVA0iDEZCAsW0j71ZE0+ehJEOBcymRBnOq2uvNXfGGFcyqjx8SJQBc5yxVNKVqPfok2sEK55Em2x0KZl8czkpsluBilWAxdTK05/nVqv1oI8dAhz+3AiXzzydWv9JK0XkiPnVebVjSIDGtCjGFsDO3hkONj6J2BgYTuFli2QaCX0Z14hqEDOUaS0a8gyQjmGLwPi2ch3ugEl3RgVu5ai4UzzMI7y0C2pWySc02/x0f7odcuHHdL9Wt9TEstSdSpA1IB1ZZe24z21xG3yRx6xMzizxQQvch4fgzmPhFYuPtsyooUwYC2WytrUSjF7Tu6FuYQdQRdRUb/2RpfmRCNqDL6UQ7CVoZUvNtlP5Gq0FnWEaSSRUap3harZIHxfwvl2OAWWDX7++Gv8Ic+mv1pP4bC4Me570+ORd7oopk92Jjp4fw5qnmsKjVk04y8FGzxRuiP/Ki8I788A+0zunXJypF4A/imwWRwJKoIFdDD4q8nP/7oQWUkJDnf8ZzZEsyygHL5Lbzgtx3gEgCceRHYxPj0J4E1I5hFwIlWariQRP4Ub5/WGuFahdkCZ25EmRrDJZZLBVBIF7VwpFxbSUCT5iyncpZmCbm6qcI49kRJgirUJEBBraKMBfZc8PL+jNafsWbErmUEdRT9sXUFK3aWVvkhH4HO8r3qYMqbZ6PAennAZCEJRyuC96yZHXGCEfFG0+tAhuIIMf23I+xgBd4cI1AjtqUDZWSLqTPG32rFuufqS6boSfw088ExdAGd/BDzDlwShNeriC8Au4kf54jcFthRTz/j8GcjP/B2GMbwD87+LKhoKaaO0vioCgyNA05mSQDQMUmmrR4deR/zYkpKMl5sd+hjFBRm9mIR5br6kSRDlLrEtWVHAxthF34DHZhrxy4GvkjjozgxN8cIRZGZwAPkxWw0+Rww8tqOOtDff/bSbk7YtVm+TK3wCNdGI6iVv1bDpz6ejkQjFF4xrqa2YFux3zgXFg2W5hQo2AfxYaM2ouMdgQ+3Z7foyqfrq5u/0M+Hk7vP5w+Y6Q5d2wpSUlgRiBgWIkEvxq94sTtYjp+wSo+/h3xFxs7JvGheOLeAB7JmsHigAnjQaHmEorTJZ5sIITEIsK2IXc+fy2YhUYbYFf7MpzvyhJtNsPgQ1CqqLNeWNYBawYBvXbYcFRu88sxXvwzws4zssbV0+SM7KMi5TFplmbSsQa17GtaReZ+1M+6RIqYwKnJKEODZsXqk5snBSOA63i8IPQ74UNaE1jjlDbKYoAy4KrDhx9nNXTAcn/xcfLH1u3/++Rp81oCWY/stsxNmD4Zl0MVUvKQySbFe4JdND1PKhlwaEvh8KioV+CIj8EmvjA8q7aX2pT3vuY16maDjSg5qMQ8cLxwfpa0pdRH9W13BXt3UIadfSpDDlHxN4ldFS8FFuY5YgflGyIVM1xr8dj4GxglsBwMNSK2WVJ3HuNpiBQrvnMXnhI/Hj5TK5XhsB9jcJ+3ARjnBmYM6kateGlr2zBUo6tasOlF5TtjmVNbBnNIaHLNdy+cRM6iosk1Zy6ZeSDJzI7ZAoe6EHvO96MMVJvxA6AlDp2zKs1J5yvNuqaofJa14C9XB1NjmR1CeQbOpxSpf9N5RKqwkXS/WV9LUu6NwgaFaVrjIrdUgFe477amkYfyWKXek2sZIgSjXkAayptXrTcomUetNkq12sbz88qhfnhp//zMyzZM/P8tfoK4WJBBI0gTDqYN1fc+2R4nOP8BpF8s5zhEa9ZJegJ79krYHBKIlvg+7IE7BbNnNyFSDtp2UIfNRIdr/+/20+WUSzZNoehqqIFjFJNSzC2BPnpcL6UX+ffHjf//8uLeOb07C/yX01v3ElrK4Tr3R61qiioAiCoKovdZzhfvOirLQBtuoP17dnF3dfH66fzi5e+BOOnuO68QYIgyKFmVzfhOy3UCXlDJEotGMgPV16LX1EgZauq2F+PuAtcq2UzDos6bBLdcEbFBTkzhY3z8+nXx7uH06/ZbkaEFVCGgtXi6MLRe36wfcw1F2f/Q/9zIOMdzZ2KqLYphcQUA79c2JeZAxDla2Qo55sDJFpMp7FpRmshJgL8ALy2YJxrh7LPR1gRGox/HLemugkwALtXWFuCYh3x/FfmBN2TSlrS3X06prsBRy9WH6vP54vLDXlMhxO2L1kRzfXFXVTC1HmPWmvMAM9tdNiSCslR2Vm+2IyjSzGEbTT3OJSpMLP7BzATAIGz7tBRBOuZIpN438GlskWeQrb2CuH1eUoxck4xPjD/eSmYVprMunxyLeLOpSVo+jcn3bIEFyGzn7EZ57bXHWhQRTSuuLspOf7s5PTi/Pz96H8pc9IFMDNL/6FG3Q0irqdJnWx3JUOPZQjtBnVr2XoTqsU/w3tQhtAJeQbfxNVC39T0ToX05uvp1ctyuzGtH5YF8rL2hgu7qkxrdjXFFXsuFAmW1IUZ3uAj6m2iYebOJg2dbQqFxTEUsiUGvtMwu3XUpenN5+u3mo2E2w8UlsIiwUNutUhvwyNU14gmcMtmoUNEFYVQb4SntFgW7osONYaov6YGzguzvTyYxkbOybZ82cIYbA3IZmPh7hYZNkHEe8IDNvEl9PDZz8wBW+G7MOTc/wDUMG1EwJUDLZLjyVhZL4mpW6G6OMnOcMtqTuATQ3WQ0cjTEwKZawX4cINfFpX6S6jZC756XA5vZmqRx/O9CVpAbslVW2Ma6pa1CGpAG3xq0rM/bdpJi1VSYJyDtwYdm5iGK3euryMcDn8ehpYYf3WHpdIxbiHkFp7nQVVkyPsD8KWDOw7fnRrnnvNaqiWYGiQn4LKGJVhUCBFX9e9cAdBXDEtR84eOgXpsJ9J9iqFVHICiwihY4Qpvhu0g6b4rBi2RAgNT26cpK8/5dwRrGrnBGxPXbcmA4xRwGw0qsY1A6TMR8ykfhEvI6SSFd4IZSqVIizzZPQz9mF9HJy/3z5z+WDffE6fr789QVKnHlPrZS29dvs2oIJQAsQvECHD3Bda37Sol1z41LOnPG4xyXd4AXQ2JSKZ9Fszm3VbOEc4rVluzJUMYkGDp8dQg0bUpBSUjWpfvTjVlkSipRN16dJELnzF5j1dBx2ftPiXZabZiYPaucMjKIT44IstP6cDcQXGsAkVbCz6hwTt0SvIQ4DtQCgLQwr5928Mpc4JwPbGk6x4xwH1EknNsvFo+UJfocpN+bBc15anzfZ9FxJhHBAWpXuV12MAat1vAvdJjm3Am4CtN+qfVO6nQi4P4rUqY4odyIfBE98Yc1MFdxZk0saX7anx0nvT4+Lk8wbsJBhvJPKanL1ZB1trMlpTE64UqxqsetlZU16LKvKKdVmxxYeQq5ytsp62R+1LGENGaUMFMhVDMqEAc/b1Bcn1/fn74WNtCY8KcZ2RXqC1k2A6XqwDEPSfd7z6ejMBda2D9r09tq0yVOuBDnHaxuYSXPo9ldd3oGyi3KG04QNVxGWHa1XOWEXbbtUamhO8ngHSwg0RinRVNAH2nARAc9DZ37oB0+L0J8fdVWrUAS+Fzvo7oEMkSqCdzDavhtDpGo+o/F8BoZQawE3eDu8IvhhPDNtoUDlWQuwRafLSl/Opj6ZbHphdY3tiiDClGfxCS/tu3Q0w+gbTOIxMNvCFHlmWsWIE1glaVXZ63h0roiy1jPh1iYMFW2bIRO+WqWTZGICLcDqIpNCiVqY2vr19uH85uHq9sv5w/ldmTTXKCx1d/69qwqgIUkcx9Il7igkVeLPgk5jqP4seLulsrO4eDx7R2dhmg2eBSg+tL33FZQpdysxcaFqKSQCiiB8Qq2F4gr3nSLe4dQe/rpHdvCp742c0PG9DhvEjG9BA81huUlzWOLz0PaMBCunHUCFK/TYd4V2eB2uFO2gWzvzRZ6TPNMTNtsD1rKNMdi9WRsa9mBcL6VlCA1q9QkNfajNKU7D8ftLZTXXdReWa6+VYmq3POd03/shxQwZLB6tS4rBGRDbFUDjIB5O0GZLlmmAcogAHs9+O/JwqTzxugP2wNF8STZpxdX5oTWcEngEZNa25S0t18UwJAX3i7nvu380V8ZcRfizzTAnPyUSiHKKsgGFZPRK2nrD7RmASZEx4pBc0cBeLMmsddyGoUdn+S58ci10ZkBbtaPocrwUQcgZv0X454QUcRYEMYPAHobu26FrwwaeIZkNlmt0rEmmlMyE8KiKSls4MY6P7e3CulK8Ju4djpFtalPm1UumVyL0tFdZGIuEe839EEHe8aPpAC12X3jvbMsQdR7hjKScsSneVdTPbP8Hv2zOJUyNPTVV5o+s4ckvQBpiXlPuRts3N2aKw1Ap21WNatwdmdwC+KAP5BdbF7LAKHu6zndla5r6eBldPIRgz4z7yukWqPLt2JiKwn0f6LYE3artz0sDwgW5TSo7SrKVk17ZTratFdgXbvtAeTzlSdk285BzpGm648efH04retdUVDblTZHbPzC+9xowOoa4IBh3QLTsgVZM42aPFc21r+0IDFNhUyEUIBVCNJosm6AWSvclUmeUSJ2XZIXIXXc2q2nweEU7xVbflx3GIl5B3SkO8uKEJJBBwhaRa5E4EkfYn0g6IFjeG8FaeErIwVdYliet2h0UqM+iYiS+qaqLMGF84hXoQ+79lvxKKqt5V27z5iXfs3HcZkfKA+NP226kJqSQaoM2AXrn8KqqcXSmSF2V9bYO0Ngej/qa6XDMennNelkQitb3Nh4nV5nA5u1anFgvxeo2pHHHsyBZ1boDifcm67kF4iaNlqfIvPji2QuUfZuCV5a5bDWAclsJNLIW08Ra2oFtlE6e2q1PXOqUVcB0otd2FFsSU6BrskW3OSo2zxNE5kZiOfm3cVsUOduwzljHq5jBlJuuN4XitivslEFm/c5tVAoz8NK5MjaiEC8qunh2O5zuxmYfGabMsbXa0t3AzCOJAybnremceNBlrW9kKQHsSgUBsrZ5S3xcj6sFQm8fCV1FTkMXOaDqQG6cVpMrCwQqT+ogUDvbcxwAqkTV4HVApb74yoHKazIgUDs74gICKpSW3yim8mEKEKjyewIqlBrbKFD5UIINGSyd9xZlNPUSc+2YUFLSRbOG7ppFSkFany9C+rJeAKGvieZWToCa7GjwofjapqTneuyBFii32d72q2LkoY+22MuWxmzBItYectno/crVI7JxZJFnJDWadYbAazIlh9rynk2dVzVZH0OOcdckzgJdATikheYE7C/Wli3T6hDWSn3GvOesvtJYK/HCXGbu1QWs5XNXAVb7kbC2bLxmhbWCQNtgdAZrtW2xVuOxtl1eC/ufdB4hu66AdqoAF4YqMGukSDftSDKhyrt9GGfkEuElQmrBfXa/WK/7UROvixylQgY4mPVU20kAeWfOjNQ6kpSTCP4c+LthfesKp2bKQCqfKNbkGoYharbJ6LbqyCb2thfx1TO6InNqfaOB1gZ3wt17IAsjXy+L9aW1wc/NTrmiPkY7GQzN6FWmme+N31SvEgWVV6wkphFXzRk6GqTq7xP6lNXcm0EfdOScQJG29YGA+MMq+XXjj7Tn+FPWldoU/mi8QsKmhu6CP7LQMP7wGYKMnt7ZGCKfNaALfBlrbVkDMDj5GCJVthcYoJG+TVVvMZ15lgIwzRHHYY3jBVEIT9ACc/5K4MmmkA8tXPYzoG1QcEcJkjssDF2fJBIjXXM5mXLH2I2U8B3amJBxBZG+bNaJaapcBtNo/k0G0SqIAM7+fvgr/KGPZn/aj6Ew+HHu+5NjGXRsE2RazAk+8OgU1yVgVAomgyMhaqhKf/wR+RUJzo2tmeO+RUsvbffZxoeben+Fk6IYI2X8RvSl+B3PD2ZE2ND3nq3AsdBPhCJWuAzsxZp1Q2uet+QlBjF+U4kjfYKLzCc7OEaPP8TpOdwn/WA+tbz4llJ0DZPAcYzN+HKC0PQ9B2GqF3+TQB+VvBMG6GZjdH/6TYQyIpTwX7Jf8+IHo+zGknuhZxn8ctDt8D0j+juOkSqzbpBQwjFzjgTx8BGmf/kjtdORPfQDCzc8Ow6nzvCXZy/i7TmeEzoUPuza1FkWrkttJ7Nu7PpWyAJn5CzmrvVGl7uOhxnUf5zZHJnElhfCDG6JT/bJWdwtPZx6hRPZktxdIU7WTcpgIvzPKYPZM49k6b62jP60pYYGsiKgQQi4LooiNWCnF+2y1Cid028PYP36rrN0OIlT+hhyRZNIqyqpMQzFOWocpQPCutV54s3VLdVIU4AzLB+r2yIp3sUfM2riKqwm27gWklHZ7lOiqEBpsjUNRwaBCWbXrK0qNU2S6cRJzNAf+ZGM3aBidDP1UVRlSIFkd4Kr1a2B4zph0pvz9OTm9PwaPxJCF5JJnSO7t39+/qnxPuz+pJ8E0r3BYt44NJCpNiQJjy9TmxhtSWNARLK2hUczyhdldZnd7TfXHoetWW+1EbisMJOZEzMsPYWBJrVkinwr8AvAug8fhKuAvAP732XU/pY2msxWkxOXgDVwbXqB9k61JrhVyArT2ign30/c07PNCURRhOrzwCm/teEeL1pS7UOiliNAMlE3hDVOjmWFtQzA1KhJVsN75pPaAx+RFt637Q39kR30TqXeCfp+4ShuEdsfzue8RoTodeZahC5ysJYSUukM5zxbIx/ETJ0vkCdlQj5UsQKEBasheVPtCntlguU85BkWEsAXn1Jw5yAcNz5CILJc13b9SWDNetn2R5n3vq7e2LQHUlmU1zc9IpHpIwBpq9CEzyosPLhglTuieeAPsV+J77cdkcZTckCC6wx2tA12zfff+AAkM3sAwFBA8ACq6BoCHsC7GQq44ZGkLeMi5rC+pLoH2egNmMrgbqAoG+kEbj/bXpKK9e/SBppz1BJt25gCFJWhAHBmM0QDbIJ1ZUBt1c3UJg1IJWmgtcFi4OMB/bUToSFw+pMkLBfxWAYq/PG6IyQ8ArTyAw9l2Fx7WC+7oPzJKtTnp/Mb/bv1U7j68Wv43VPdtz/PQsrCu0+321ZIVKSepPkAvBBwE8MLWxvOVLjvdP1qRPZPk3jiJ+SZ2EUubmdd5Vec1qdpKqy126CYLUSeQv8BCab15/6CDNYCnKzM6wv0GQ17HYT/on93t9fXT2dXJ2QWbHzt69UHOXF22Bd44nqjJw6MALXc4dIlhIlj+CH2Y2OGEg3hGr4NsZORPeSDhN5OQosyqFzXJaThNHt+8PieSekqixwAiQ1DFVDdC0VkR6oc6L73v9v4Fr65bG8wPGgKmD/VcLdxBRp5xtLzluXCOxRNli4XLttHs6mGeGyvIjaxs2zOt6SxTYhX8r76lG/tYnn55VG/PDX+/mdkmid/fpa/AO71xyiIGGVvpCIX5PXawEXu4W1EQ1kiAhpsmVB+rSiwxRvbUFCo//70+Ldufr578y7PXy5mt2861K+/QCEtkRCWaTUJKDk8HAuPr3zTUIY/ARWpYIBH1SsALfgIPG+6f3zCSXdE+cdXiE1xffvYpg7SVkX5ZniQVjnAdQavcYDrWnMWgrvh9Y38dM2rs+vz3Ugzm6tZHykmiSiUFsEhuzUF8sBHgIY6vzeS20ztr5i8oGFPRRi9SWdwmY66qLczeNJMJMZKTV7T3ZZdbxavN3daTmmmyT7i8EnzWR+HkptDyc1+ltyACtnl1efLQ6FNcaFNZYIFaI1VKICaV9xAs2nv3Yb1HzNsjnZKPQfyWZqspmpOQ0/a7LWmofNaBxkK5oxIWvcq4gZUehwl6eD+3I6WXBDRsEoVJyXpJPlo4o0+RFJFNXgiM2Fa1QDwBPKqVBGwARnEO86Gqtq/AcKntYBK0a5LMVB4/vmuxaj1804ZGpPQKO+Eiuo+vJ7agM8RGj5fRAZ1z+ETVZXxQbD9U0v37GHvZJQcaVSZF4Jv/DHzQyT3EJCi7gg9UlYIKgSL0CHfQDQIWgy2UiEOwr/kgGmmYsaAUrR0qMirCukPPwMf1YvUvC2URdI2aHRQF6tUF2Wtz9RZKUAcThIaxhrejvv89er26e78+uQnNhs8Hk9CZ2Yj1jGbP4XLwLNHt16PJgF6/kv1M8aqOQCRoVkJGv1b1zRy+BGgDI2DO/ngTt5HdzLbGOSj+5BjcNbqQJZK6uBi5ZH/5pVwoWElnA+bZ+XmmB/d3gkxKDHJilqTzdRhLOXFYGBjzaKXdHbrIiBFRWAVOhNSKUSw10NtSoXEZ+6/z8lwm3HW8gVXu3FUvSRLlSp3NuYwQjPb6cY0JDajuGZOKPHhidgKEI5BMxMyH9g1fZ7mt5+tWxG9ywI7oliDvJs1jV6HYc87kTNSKDLKbi+ANj/cKWCBlbXieN9RVP0TLXq4+nJ+++2BXzaw7Tl6/0gFbpEw9jBYrryOXWPtsmawLWfAs9ZAW72KfGT4tAvmL8bqszBbPKCD9Zdhmwy/xVhQeQbd2hAROJzeakl0cx0zq8uaKGvcSGXnBzR00BJHxAPfxx8bTu3hr5h6ASda6WlYtQlAiTW5AG2XjoBrRNelJU77SzR5am3zyWi0j9FaelO6VUag8NGyNT1qGx07Vw1p6qrMz0SC+tlKicnaSEaK2K5U20ANyZuTpq9LBmyBEoEGWA259XZDBl7yraNEtPFrHLLLnm/5SGFgL5zfpP1pdFhxHQS6ufqpp56BZ1OIyEB/y6HvefYwjL+lF6fA5JKq0BdUXc6QKj35Tgx+L0S5UslKiWGYa9p1KNtTYaOCUCS/0YwlpZaIbLEtvy6/rEVbXGf81aXHqap1CTWjTZm2XX57VulMRFyOSMuUKW8vvIqS2Ndrka1luxdtOy26iq21TtCOwqayi6W7ylQR7SlKwn3nkJSN9iHJB3oOaYDtpgGqQFvyGtMAYU7FB6YjLZs01XsigwYirZs22tsTE1jWmPCMBs1BgvxTVbRohs+CJ9EkABIrYF1kdrom9LWsiaJBbQqEVZSkGdQ+uPvqcDIUspH1VYllxzs3pKiZ7wdHGj9TIDZW2PioK2fKZxjEImxqeUh72A8BJiGVkgk6g71hGnbh0lN9DwTVwcJ+GKZALKUQ8ztCiBIfS3n3PSAryhgRVUb7BFr41tcAEp4MWeBv9+dtMM0106HyjyJfVVWMvmEIyR8xewawlV4jC4UPYp1HF6deFTtoo4GJ52dVGAw1nAJb2KRJENzr8tLCQN97ubWzsVA4vbasgCtkPeun1+bMfmtoInSer6QwIvmOotdSZdHrGnEFGGFREM5uDVd4x3VBw5v17HrrGGj17JuLgUKOs7pioDCweccZT4qN9K7eEfvXM0AFPppmulqrbGdg9kTL1mPx5VjZ+1RXgwBDMddDkKfqNpVZUjphJItTBVSRS8bHQl9W6NSATuSSwMNodfA09kgx64JQBXoiwaeRw38aEqp8/QpNho7I11ncRbHMPTFXuSCVDuUb1RWkgjGAdxNkq3S6aXJqSh/pHzmGvwlBtb5CTBiueR0SU+1U47wrbtCZfor/JkHC1QfyOinuGQctruasj21KgC1SQDQ7sE1YjTpWDKUvZwfIm0KNFZ3ww3WwhLgCY/gd2MLl8U9tU2wDFfs56QybFe3WISYMtkjfgBJIBbFPvbSNGLgS73mqvudB9eDUmGRcQ+PlrKHVJWbBDfO8ynVmDklrm9ukWZn7jG9CWpaJaVkLdFdiGiOZceMerpcNac40wJJ54fovZFaxg8unSd80/GVTfzmZcmf47vPoiEcq4tVmD4qmbRw4UxWD0YhFUTY5pIImP7EDuCoLc7aaQrJZgveIGauWFVdrErnLhqubamVh6FnuoujNepFKjPvqrMpTjAgl9JbSKopZSM/HaKsyTWPZESEMhjGg+/aF1B+pFHZsOguH/VaaRrpm+swr+JDbuNHQy8DH8ma1HLHx6Rd/hN2V5/8H
\ No newline at end of file
diff --git a/main/config.hpp b/main/config.hpp
index a639703..2c82a07 100644
--- a/main/config.hpp
+++ b/main/config.hpp
@@ -17,7 +17,8 @@ extern "C" {
#define GPIO_VFD_D1 GPIO_NUM_15 //ST1
//#define GPIO_VFD_D2 GPIO_NUM_15 //ST1 (D2 only used with 7.5kw vfd)
-#define GPIO_MOS2 GPIO_NUM_5 //mos2
+#define GPIO_MOS1 GPIO_NUM_18 //mos1 (free)
+#define GPIO_LAMP GPIO_NUM_5 //mos2
#define GPIO_RELAY GPIO_NUM_13
#define GPIO_BUZZER GPIO_NUM_12
diff --git a/main/control.cpp b/main/control.cpp
index 85881ee..a6199cd 100644
--- a/main/control.cpp
+++ b/main/control.cpp
@@ -30,8 +30,8 @@ QueueHandle_t init_encoder(rotary_encoder_info_t * info){
//====================
static const char *TAG = "control"; //tag for logging
-const char* systemStateStr[5] = {"COUNTING", "WINDING_START", "WINDING", "TARGET_REACHED", "MANUAL"};
-systemState_t controlState = COUNTING;
+const char* systemStateStr[6] = {"COUNTING", "WINDING_START", "WINDING", "TARGET_REACHED", "CUTTING", "MANUAL"};
+systemState_t controlState = systemState_t::COUNTING;
char buf_disp[20]; //both displays
char buf_disp1[10];// 8 digits + decimal point + \0
@@ -75,7 +75,7 @@ bool handleStopCondition(handledDisplay * displayTop, handledDisplay * displayBo
//stop conditions that are checked in any mode
//target reached
if (lengthRemaining <= 0 ) {
- changeState(TARGET_REACHED);
+ changeState(systemState_t::TARGET_REACHED);
vfd_setState(false);
displayTop->blink(1, 0, 1500, " S0LL ");
displayBot->blink(1, 0, 1500, "ERREICHT");
@@ -84,7 +84,7 @@ bool handleStopCondition(handledDisplay * displayTop, handledDisplay * displayBo
}
//start button released
else if (SW_START.state == false) {
- changeState(COUNTING);
+ changeState(systemState_t::COUNTING);
vfd_setState(false);
displayTop->blink(2, 900, 1000, "- STOP -");
displayBot->blink(2, 900, 1000, " TASTER ");
@@ -188,19 +188,22 @@ void task_control(void *pvParameter)
rotary_encoder_reset(&encoder);
lengthNow = 0;
buzzer.beep(1, 700, 100);
+ //TODO: stop cutter with reset switch?
+ //cutter_stop();
+ }
- //######### TESTING #########
- //stop cutter
- cutter_stop();
- //######### TESTING #########
+
+ //--- CUT switch ---
+ if (SW_CUT.risingEdge) {
+ cutter_start();
}
//--- manual mode ---
//switch to manual motor control (2 buttons + poti)
- if ( SW_PRESET2.state && (SW_PRESET1.state || SW_PRESET3.state) && controlState != MANUAL ) {
+ if ( SW_PRESET2.state && (SW_PRESET1.state || SW_PRESET3.state) && controlState != systemState_t::MANUAL ) {
//enable manual control
- changeState(MANUAL);
+ changeState(systemState_t::MANUAL);
buzzer.beep(3, 100, 60);
}
@@ -242,7 +245,7 @@ void task_control(void *pvParameter)
//--- target length presets ---
- if (controlState != MANUAL) { //dont apply preset length while controlling motor with preset buttons
+ if (controlState != systemState_t::MANUAL) { //dont apply preset length while controlling motor with preset buttons
if (SW_PRESET1.risingEdge){
lengthTarget = 1000;
buzzer.beep(lengthTarget/1000, 25, 30);
@@ -257,11 +260,6 @@ void task_control(void *pvParameter)
lengthTarget = 10000;
buzzer.beep(lengthTarget/1000, 25, 30);
displayBot.blink(2, 100, 100, "S0LL ");
-
- //######### TESTING #########
- //stop cutter
- cutter_start();
- //######### TESTING #########
}
}
@@ -275,12 +273,12 @@ void task_control(void *pvParameter)
//--- statemachine ---
switch (controlState) {
- case COUNTING: //no motor action
+ case systemState_t::COUNTING: //no motor action
vfd_setState(false);
//TODO check stop condition before starting - prevents motor from starting 2 cycles when
//--- start winding to length ---
if (SW_START.risingEdge) {
- changeState(WINDING_START);
+ changeState(systemState_t::WINDING_START);
//TODO apply dynamic speed here too (if started when already very close)
vfd_setSpeedLevel(1); //start at low speed
vfd_setState(true); //start motor
@@ -289,28 +287,33 @@ void task_control(void *pvParameter)
}
break;
- case WINDING_START: //wind slow for certain time
+ case systemState_t::WINDING_START: //wind slow for certain time
//set vfd speed depending on remaining distance
setDynSpeedLvl(1); //limit to speed lvl 1 (force slow start)
if (esp_log_timestamp() - timestamp_motorStarted > 2000) {
- changeState(WINDING);
+ changeState(systemState_t::WINDING);
}
handleStopCondition(&displayTop, &displayBot); //stops if button released or target reached
//TODO: cancel when there was no cable movement during start time?
break;
- case WINDING: //wind fast, slow down when close
+ case systemState_t::WINDING: //wind fast, slow down when close
//set vfd speed depending on remaining distance
setDynSpeedLvl(); //slow down when close to target
handleStopCondition(&displayTop, &displayBot); //stops if button released or target reached
//TODO: cancel when there is no cable movement anymore e.g. empty / timeout?
break;
- case TARGET_REACHED:
+ case systemState_t::TARGET_REACHED:
vfd_setState(false);
//switch to counting state when no longer at or above target length
- if ( lengthRemaining > 0 ) {
- changeState(COUNTING);
+ if ( lengthRemaining > 20 ) { //FIXME: require reset switch to be able to restart? or evaluate a tolerance here?
+ changeState(systemState_t::COUNTING);
+ }
+ //start cutting if automatic cut is enabled
+ else if (SW_AUTO_CUT.state == true){
+ cutter_start();
+ changeState(systemState_t::CUTTING);
}
//show msg when trying to start, but target is reached
if (SW_START.risingEdge){
@@ -320,14 +323,26 @@ void task_control(void *pvParameter)
}
break;
- case MANUAL: //manually control motor via preset buttons + poti
+ case systemState_t::CUTTING:
+ //exit if finished cutting
+ if (cutter_isRunning() == false){
+ //TODO stop if start buttons released?
+ changeState(systemState_t::COUNTING);
+ //TODO reset automatically or wait for manual reset?
+ rotary_encoder_reset(&encoder);
+ lengthNow = 0;
+ buzzer.beep(1, 700, 100);
+ }
+ break;
+
+ case systemState_t::MANUAL: //manually control motor via preset buttons + poti
//read poti value
potiRead = gpio_readAdc(ADC_CHANNEL_POTI); //0-4095
//scale poti to speed levels 0-3
uint8_t level = round( (float)potiRead / 4095 * 3 );
//exit manual mode if preset2 released
if ( SW_PRESET2.state == false ) {
- changeState(COUNTING);
+ changeState(systemState_t::COUNTING);
buzzer.beep(1, 1000, 100);
}
//P2 + P1 -> turn left
@@ -400,7 +415,7 @@ void task_control(void *pvParameter)
displayBot.blinkStrings(buf_tmp, "S0LL ", 300, 100);
}
//manual state: blink "manual"
- else if (controlState == MANUAL) {
+ else if (controlState == systemState_t::MANUAL) {
displayBot.blinkStrings(" MANUAL ", buf_disp2, 1000, 1000);
}
//otherwise show target length
diff --git a/main/control.hpp b/main/control.hpp
index ea9f5c7..6c2c7dc 100644
--- a/main/control.hpp
+++ b/main/control.hpp
@@ -26,8 +26,8 @@ extern "C"
-typedef enum systemState_t {COUNTING, WINDING_START, WINDING, TARGET_REACHED, MANUAL} systemState_t;
-extern const char* systemStateStr[5];
+enum class systemState_t {COUNTING, WINDING_START, WINDING, TARGET_REACHED, CUTTING, MANUAL};
+extern const char* systemStateStr[6];
void task_control(void *pvParameter);
diff --git a/main/cutter.cpp b/main/cutter.cpp
index c1b04ce..e658103 100644
--- a/main/cutter.cpp
+++ b/main/cutter.cpp
@@ -55,6 +55,20 @@ cutter_state_t cutter_getState(){
+//============================
+//===== cutter_isRunning =====
+//============================
+bool cutter_isRunning(){
+ if (cutter_state == cutter_state_t::START
+ || cutter_state == cutter_state_t::CUTTING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+
//---------------------------
//-------- setState ---------
//---------------------------
diff --git a/main/cutter.hpp b/main/cutter.hpp
index d45920a..9e86a7a 100644
--- a/main/cutter.hpp
+++ b/main/cutter.hpp
@@ -28,5 +28,8 @@ void cutter_stop();
cutter_state_t cutter_getState();
//TODO: bool cutter_isOn() (simply return boolean instead of enum)
+//check if cutter is currently operating
+bool cutter_isRunning();
+
//handle function - has to be run repeatedly
void cutter_handle();
diff --git a/main/main.cpp b/main/main.cpp
index c7b150f..a60baa3 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -32,10 +32,11 @@ void init_gpios(){
gpio_configure_output(GPIO_VFD_FWD);
gpio_configure_output(GPIO_VFD_D0);
gpio_configure_output(GPIO_VFD_D1);
+ gpio_configure_output(GPIO_VFD_REV);
//gpio_configure_output(GPIO_VFD_D2); only used with 7.5kw vfd
//2x power mosfets
- gpio_configure_output(GPIO_VFD_REV);
- gpio_configure_output(GPIO_MOS2);
+ gpio_configure_output(GPIO_MOS1); //mos1
+ gpio_configure_output(GPIO_LAMP); //lamp
//onboard relay and buzzer
gpio_configure_output(GPIO_RELAY);
gpio_configure_output(GPIO_BUZZER);