mixer 结构分析[uavcan为例]
mixer指令为系统的app命令,位置在Firmware/src/systemcmds/mixer目录下面,其功能是装载mix文件中的有效内容到具体的设备中,然后由具体的设备中的MixerGroups来解析这些定义.
本例是以uvacan为例, 系统运行后,设备的名称为:/dev/uavcan/esc.
uavcan的定义中有MixerGroup实例,Output实例.
MIXER的种类一共有三个:
NullMixer, SimpleMixer 和MultirotorMixer.
NullMixer:用来为未分组的输出通道点位;
SimpleMixer:0或多个输入融合成一个输出;
MultirotorMixer:将输入量(ROLL,PITCH,RAW,Thrusttle)融合成一组基于 预先定义的geometry的输出量.
![](http://blog.chinaunix.net/data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAukAAAFjCAIAAAAPZQJ/AAAgAElEQVR4nO19u83kurK1YrkZHGxPwEnj387Y8k4C2xrgT0DuHHdyaOAGMDk00HbHoWuoW+JbxXcVtRY+fOhWa5HF4muJLEnTBtDwfL97myAGTl9N06/2lvAH2hUd8BUddF+hY6Jd0cHHV1NvA8SAT53xB7QLHWhXdMBXdEC70IF2RQcfX6Vrl5wygHtDLnGIZGUzuOBmcnshR7tI9DO4Y3NtQLuA24gL7QIuuAy5WHeRqE17oZev7Hyn5/utHt2/1j5y/O+SO2zucuQYIgXZzNDPdysvZ5splONgQkZ2IjUM3jsm6hc2c7D5OH55DuJdqLB9B/jg9BUu75xAu6JDoq9ybG7DxZ4RuBK50C5USBw3ewHahQ60KzrgKzpytMvdgHZFBx9fQbtQwafO+APahQ60KzrgKzqw7gLuSFwbiNUFtxEXsbrg3pDbC1h3oUNi/fYCH19Bu4DbiAvtAi64DLlYdwFXIhfaBdxGXGgXcMFlyIV2AbcNNweI1U0Hn7Uy/kC8Cx1oV3RI9BX/OQbaBdw23BxAu6QD42YmF+su4ILLkAvtAm4bbllAu1DBp874A+sudKBd0QFf0YFYXTrQrujgo3sQ7zIytxegXeiQWL+9AF/RAe1CB9oVHXzmMmiXkbm9AO1Ch8T67QX4io4k7fJYpnl9+U4M/+rGa52jOc3h99VFkRuXjoMz+cyD0C7gNuIi3gVccBlybe3i4ZK0i86Nm22tfCPUUh1fhQ14rfP8zx9Kvu50Im3WnJmst+LzLcbNAWJ10yHxmo/VuAntAi64DLkVtUvkQoEw7fJa53n932b1qzuTf7sqC2iXdEC7ZHKhXcAFtyb3sUzzui7TNE3T9K+ff7bH5/M55b3WeTKPTdN/Pud9jz/fv5U5+5i/H/rBD5aHkv+kHdVmW+3XdZ0n7ad5fW3b8/cP4xw9EztTrcjz+nIUWc14eURTjsOe0j3fb0Kaewlf6zzpLvzr61hXuR67Az7HFGc+lmn+5+cPT3a+vM4vf2vZOfLSG5Xmvb+nv7SSOmuhCaBdqJCoXXoB8S50oF3RAV8F8ViO2ee1/kv5PCtz/2d2Oj++rCl2s2SKcfB1Ko8j8ZeqRh7L8tBmW+tX9cAnXUcKqhmuTPUiz44iv9ZZmf2X7zyvU57vt0ExHRIu3bUZtuuOCvCXS1MB9OwCeTmzs/NSMzW997emJI+GYR90ALG64HIHtAsdEuu3F+CrIDTB8ffnml45rk5hx5fXOk3/fpgpBLXLOcVu5xd1mjt+0YSHcVHvTNZ3jidTt52bR3N4TzvXTszS+W0z15SCZl**TWlFC5XbHb+vNzZ+ffFXN7T25WzFhyrNzugXcDlDmgXOiTWby/AV0EQtIu+e/RZ2ojVLuruibrToW8vmLEuxubDkZx7J8qaFN2ZXokGx0x6pV1MhecwwCpdjHYxhNB1uT4Ucnb+vNzZ+bWLy3tKu3IqLU0cGcB9RuCK5CLeBVxwa3KLrbtcxLuELq235/u9bxzMvjBd/XJ9VXI6y/s5x5AOzmiMzwlumx0zadK6i2n/WTqN60nfXndZlu9e1VW5vhz162OZjvubrtddFqva/6u1q/C6S0C7RK+75ACxuumQeM3HasyFdgEX3JrcK+2iBiOcU8xDXzjZ5/I/esCIP97lGwexPZb9yCd2ZJ5n/XJfWwpQjFBXIP71849+jidQ48j0Uru4412C2kXN9HCYaf9Zukjtoq5VTH//fl+W65uOqgeI2kXLS3Xj4efXuhjrNKbHHPEu33alNKEriVkADu3yfL/Vo/tXHLGPHP+Z2OM8UjBBNc0EM+xzpulXbScUt7nBEdgMmwvZ/Pvv6a9jSts/P99vdVJ//vn5r0m7HeT5fk/Tv7/7B8s+KT7f7+OWn3ldv0n9VoXCca/Kfkw7si+n/PitWKjuVRyiavvvj2k/7Wuzec73vqgf//1IhOP3n/+riIa9mKpcO4qvsX78tkqhnmaWfVoWpexn3v/8/DH9+K1UhOb5M50zr92eP//8dc7sey5//74s1/v5+8fJsrIzirC+wnnpfv7r58vI6/3n0CvfvM7tJbOWX9Y5Z9m9stv5U0I3wboLFYHKAAw4fYV4FyfQruiAr+ig+6pGxzQWCjwIxUa0RGy7opWuGBpnF4S6nnce9O466SjbfxHvMjK3F6Bd6JBYv70AX9HRVbvIki4Je3N3lS7QLuC24fYCtAsdEuu3F+ArOvquu1BQLTQiGmhXZHTTLjYX2gXcRlzE6oILLkOu3TH52wwuuIh3oUKiNufTzjZoF3DBZcmFdgFXIhfahQpol0wutAu44DLkQruA24ZbFtAuVPCpM/5AvAsdaFd0wFd08I934QO0Kzr4+ArxLiNzewHahQ6J9dsL8BUd0C50oF3RwcdX0C4jc3sB2oUOifXbC/AVHdAudKBd0cFnHoR2AbcRF/Eu4ILLkIt4lyjusmifiVyDRc/XSaRwfcQwN8Ai5hsAF+1yN0jU5nza2QbtAi64LLnQLrHcZdmmadr/05HGak88WN39HOZCu1AB7ZLJhXYBF1yGXGiXWG6akkhmtSf6hEumn8sC2oUKPnXGH4h3oQPtig74ig7Eu9CRvO4Sy9o8GzGsiPXWXcoC8S4jc3sB2oUOifXbC/AVHdAudMTGu+yLE1uMLLiMI2FCvCwdnz4I7TIytxegXeiQWL+9AF/RAe1CR8Ke0T67D4lw6fjMg9Au4DbiIt4FXHAZchHvAu2iYnztcjdIvObj0842aBdwwWXJhXaBdlEB7TIaoF0yudAu4ILLkAvtAu2iop52KYthK6A4+NQZfyDehQ60KzrgKzoQ70JHg1hdKZAUq/t8v1Vr9q+1jxz/u+Q+sM18zLDPmaZffBzF54jtNG4W4ojEI3YD87H2jsnB5l5HbKeFWWn3SEvBUbqy7TAnEecRxOqOzO0Fp824vHNCYv32AnxFB91X6Jix7Wpg4bJdlY7PPAjtAm4jLuJdwAWXIRfxLrHcm6y7OMGnjhDvQoXEaz4+7WyDdgEXXJZcaJcoLuJdkhOHdukDaJdMLrQLuOAy5EK7JOwZ4T6j7hi2AoqDT53RwWosgHYBtyP3bkC8Cx3QLirG1y4Sx6+7cXsBsbp0SKzfXoCv6IB2oQPaRQW0C7j9ub0A7UKHxPrtBfiKDmgXOupol8cyTdO0PMxD8/raP+4fcvBa56lAMjrGf64unzKAWxnhbub49VK7vNa5dI+Lgm1zqIxVrTV81dszrCGxD/LnIt6lpnZRxMtrnaeppNZ4rfM8z6XFy/ja5W5goCGiUaitFNcuoQmaYLPXHnJ5jxTOD39Pf3lMupYT33xTrqV0m+nS5bFM8z9/uIwj4MrlQrvUuc/osUzzup5Dwmudle/7WKEvnDwWZVXmg6/0eSzTvD529fM5tg8WypDxzXFSJZLzYHrp+NQRtAsV0C4exGuX4ATdVrucR7zahSAnivXJyFUXPuMIuHK50C6xXNrzXfZBxrhMsq+aXutn5eSxfFTJcWT/uCsVZbvpg+9gcQ4aj+UQNoYMMg+ml47PPAjtQgWfOqPj+X47dPfD0uCfxUzt2PP9+9D+rj1auxNurssF9djZNc9stF/XdZ7+9fPPZuegn6Nncv78929l/SNUZM+6i+vqJHRZ8032a7PlWW2wcF9L/fP753EtRclLPeGfP3+Sr9sc7fmluNao6IPoaCr+VuHyp66JVSuvrxrPtgFcAfEudCTsGRGe7PLpCx/58VjORm4Mm6913se1va+eekX9Yl1ufRL0nXMoIefB9NLxmQcR7zIyd9s2TXfvE4/ZQ5QGfX5UtL9XpvguILbnn5+zdQkxTf9ZjAlazWR7LPvMaORqnaOb4b9GuSiyqV08Vyeq0CIma19IBe3866ciIWPzUlOOvW4z4Kxxg+hsKr5WEb7ae62zsvi9fNXZxVWjb18PMAHtQkfNdZdPH1wWQ0loWkTtDNql2nn5YWoX8yzXwGgRNVmUVjpoF3BbcLdt80wtymdNi3+/aI2cpl0UyvP95/NF6ZSfIVKdoLUuG0jWdw7lGiWst7yrR9qWMtGTuitWp2mWnWfMSlpem5Ud8brNgNkMXLk7mwptNc4cMTVJ6szUkfjfhKtGYAe0Cx0V410OyX9+dPffRb0WcDRzo/+eqy7K1wLrLreId+FTBnCDIGgX/QLgo+BjtYv7csHcGTAjOox9gyM568rffQlyfY2SoF1eqgxQrI3QE6bi8tt5aJfkvMzsaNdtJrTf/drFbirX5rmu9hyj6PVV4z9/pWsXif0X8S48ucfsHoTWcfxr2GpTt9ZNv2uSZv81pMsnEedlhu/aI7F0fOoI8S5U8Fkro+OMd4lfd/nX9CNeuxzrLs5Y3X9P0zz7glG/9OfvH5MWnm+f4+2Nrvt9qNpFidVVBxHjWsed7JerrbsszkUKszyHdqHmpVr+4aZct1l1FLPu8m1XKesun3wdeqbuugufMZcbF9qlunZxHHwc+8v6KHHqmA/MBZvNuWj5Wudpnj3xavbB9NLxqSNoFyqG1S7GiuZ3AjznifN3bUHCCuBV4l3e78/lwnnBsU3T/5vnWZuxlF+PufsbI3yuIljnqHOh1o3/9+cPv8baXDOrS7tolyzGwixFu9gXUqad6rXUV7tQ87K0S9J1m6M9K9YqLcKWFPP6er7fyunhVrEZZ04/fh8OseJdLq8af6RKF0ZjLjcutEsd7dIeYbVERT3tUhYMK4Ap+NQZHTTt4rnP6PeP75bDYu/RWA8q2LSftcuFA/+zrsZSp+Oa4Pl+6wsHjnO+9ipRqDs+ca9p2sW6OjEXZinaRbHre8Cxl6NcS320CzkvXbv8SbpuO9qGjoOk1rhBdDUVT6uwr/ZU7aKf892ntCjawZzn2dwNiHehA9pFRbh0fOZBxLuMzO0F3/NdzAnaDVIwfAPQrM3F7qs2eZERPd6VSOF65JXYF3oB2oWOOrG67VFAu1SN1S0LaJeRub3g0S7/gXSx8V0ba1Vk7SEu2jrHfgP6tpWQLtAuvQHtQkede6Slot490oXjXZ7vt3p0/1r7yPG/S+4D26ya2tEY1Z7j6z5EXqbzWKbpx28+Lr3PEWV75gwrSU3599/TX+oWD4H12CmBdIwGlt8miUfsREr5nIPN0/RLnM19/TywcNmUZ9MV8bPRYQsmy3DTjilUP0pBjs3FucTLO1Y2gwvu8FzE6sZyse6ShrJcaBcqoF0yudAu4ILLkAvtEsVlHO9SALeId7kb+NQZHazGAmgXcDty74Yc7XI3xLYrrvcZlQHuMwK3P7cXcrTL3SCxfnsBvqID2oUOaBcV0C7g9uf2ArQLHRLrtxfgKzqgXeiAdlFRT7twiXfhUwZwuQHahQ6J9dsLEvsgfy7iXaBdVIyvXe4GiXMMn3a2Id4FXHBZcqFdoF1UQLuMBmiXTC60C7jgMuRCuzS4z0g9M+rupMZE3Gc0IPjUGR2sxgJoF3A7cu8GxLvQEduujiegOJ5Q7Ucaqz2x3vNdygLxLiNzewHxLnRIrN9egK/ogHahI2HPKEFJJLPaEwPrNHz6ILTLyNxegHahQ2L99gJ8RQe0Cx0J6y5b/IPpEliTsneT8By8GnbymQehXUbm9gK0Cx0S67c**ZB/lzEu8TGu6ifiVxn9Mkld18FcSZyyQ3EuwS4l1EyfOoI8S5USJxj+LSzDfEu4ILLkgvtwpZraJdm+YrgQrtQAe2SyYV2ARdchlxoF57cI/qkcb71uGUB7UIFnzqjg1X7hnYBtyP3bkC8Cx0821VAuHQEH18h3mVkbi8g3oUOifXbC/AVHdAudPBsV9AuYUC7jMztBWgXOiTWby/AV3RAu9DBs11Bu4QB7TIytxegXeiQWL+9ILEP8uci3oUhNxzsUi9fQVx2so4tJM4xfNrZhngXcMFlyYV2Yci9XHRhaHNj7jRNv/CHP/zhD3/4wx+bvx3dzWD8l6yD7gasu2RyJ6y7gHu//dNeQLwLHQzbFc9gl42TrxDvMjK3FxDvQofE+u0F+IoOaBc6CrYr48VAmemUsqog+PRBaJeRub0A7UKHxPrtBfiKDmgXOkq1K9+rDdPSKWJScfDpg9AuI3N7AdqFDon12wsS+yB/rt0x+dvMk2tojksR48uXol04lLcvl6m4YwiJcwyfdrYh3gVccFlyoV2KcH2CI7AS4xknSYsu3cvbnQvtQgW0SyYX2gVccBlyoV1KaZfwmbaCMfKN2mPqXt7uXGgXKqBdMrnQLuCCy5BbVrtIRH55oyJUfGExyfExLcGnbSDeZWRuLyDehQ6J9dsL8BUdiNWlo7F2USmCVMsOPn0Q2mVkbi9Au9BRtX6Xxf1ZaI4S+0IvQLvQ0UW7qNzM3FuCTx+EdhmZ2wvQLnTUrt9dQLQRLrVzlNgXeqGXdpE4TmZyk1dNhJaXCVeS4usLieMmn3a2Id6lJje8fb4soRNq2BwQLt19Ba4BxOoW0S7t8705F9qFCmiXTC60SzLX3oi5DPczhEtYvthSJrz1E7Y5vO7C2c/35EK7QLtI5EK7UAHtksmFdsnhhiVIgOX8rCIgenysgM2XOTL38w25uM8os7zJ2kUi+LQNxLuMzO0FxLvQEa5fewWl9kDZPkc6JPaFXkCsLh3QLnTw6YPQLiNzewHahQ6PryJWQSrBt9LTzgILEvtCL0C70AHtQgefPgjtMjK3F6Bd6DB85dwP4nCrs9OwxpDYF3oB9xk14yZ3B6HlZcK9i1rMh8Rxk0872xDvcsXtrgwoyFcw3f0MrgHE6kK7SOQyHSIZAtolkwvt4uOKUC0Gkm0WWkcDc6FdoF0kcmUMlBwA7ZLJhXaxIVG1qEiwX1wdDc/FfUbF412EdmcK+LSN6fl+q9bsX2sfOf53yX1gm1VTOxqj2nN83YfI7s7p6JYjiGT/LFq1qDAUTGylDNYHxR1J7pgcjC9yxGiNlyyjz6rNPrkjDHmkai6I1R2Z2wtOmxGru7lu3ultUTE0WEOS2Bd6ge4rdMyEdqW2c+PDYP3aAJ8+CO0yMrcXoF2cUIVLy7udW+KQZRvexdgVvbSLxHEyR7v4UClfcA8MKw+LQ+K4yaedbYh32bbtHusuYXHGv47uxkWsbhoX2qUvd5yhszagXTK50C7qpD5wvEt4VYl5Hd2QC+1SXLtUzRfcHbIHzZaAdsnkQrtsunzZBr3PCOsusri4zyi5vJnaRSL4tA3Eu4zM7QXEuzjhiwWROPD5bEa8CxMgVpeOnHZ1K+GyceqD0C4jc3sB2sWHwOgmYgSkjNT17JfYF3oB2oUOaBc6+PRBaJeRub0A7eLD5ejGdiikGwbtwgG4z6gZN7nDCi0vEy6XkZE/JI6bfNrZhniXbdvI87otFLqImDQzwqfxr6O7cRGrW1C7tMz35lxoFyqgXTK50C5b/JqEUz1U1TH5OUK7yOJCu+RzoV3ac6FdqIB2yeRCu2x5+yk+VVEPOXb6fuVfR3fj4j6jIuXN6TKCwKdtIN5lZG4vIN7Fh1IDHDe9UqOMNiT2hV5ArC4dpbRLfiL8wacPQruMzO0FaBcf7nBxdivtot4Hzuo9D9AuKsLVxLBdsUVVX0X1JmiXkbm9AO3iA7RLDnj2BefzBgV9nqZf3W1o8FmtJg724LPz8/HYcQOId0mHRO3Ciot4l6rPbWOCyzIyr6M07l7q/TOTOYD++SbaZZKsL2/1mThuQLtQ0euaj+14HcuFdtmunpc/BujvBJi+IKbMdt1l4ydGe+0Zse2DgWpia/MNub7RA9olHdAumVxol20bX7hsV2U07imlC5eNpXZhu5aGeBcViHcpBcS7gHs77sDahQ6su0wW6CnznGNiS9EG0C508GxXPMHHV9Au4DbiQruwvUYviEAZbdUSO+VLbBv8uXi+y93Km4PavqIPC9Pz/Vat2b/WPnL875J7EZvtr+ppBv04mGCGnUibIhe3eZp+ibP5skkYHy5ZPK/Ry8Iuo1O17Oc4u9hBHLUvsLL56JgJNt/NV7A56khCvvvIQMll8GG0IFTHgZvAHXjdhc69m3bxqZY0P/Cs33BZeNqsAu8EAFcid/BhtCD41JlQLrTLdiftkoxAyjl1VA886zRHu7TJF1xwc7jsuhxb8KkzoVxol43rPFcW9HWXWE3DU7vwRC/tIhFoV3TU9hV9hESsLriNuANrFzr0nvlYpmmalodywmOZpmleX/vH/UM6Xut8Tv65iVFhjz4BORL4NaxjgDCgXeiAdqED2gXc23GhXTa3dlHEy0drlFEZr3VW034sjcSLb/QhqpBKIgbxLj7gPqO7lTcHfHwF7QJuIy60y+bQLvO6nssrr3VWvu/rLq91VsTMY1FWZT74ypPHMs3rY1c/y+O1zm4NpJ+2qYszajb256+1+qmKIZ/0wnN5vnzxnRD2PLSLD4jVBVciF6uvVPCpM6HcgbVLarzLLgt0cWB+3XZxMa+vXSYccuOjHl7r/FEvynbTFthx0k8701Q/+rSL8vt+UFNIj4WgXVQ/0FXOZukV+5xwgvzbRi8utAu4fLi+Lgztkg4+a2X8kaNdJILYNqzntn1kwUd+PJZpeZjrHMeCzLSsh0o59Yr6RVcrIe2in3YmdXzxr7u89DONfanIdzHGypfn9wE5Nit2GWZ44D4jcCVyoV3Kg3N9i+Bi3WUzn5f/VQOvdZ6WZTF0gyYyNJGgbtNM0+QQHNq3h7bPE5A4ThnktEdRT4ox+xH6uxiJULWLesQ5xrUXMTylEmJ16cB1KR18fIV4lxbcu+Fu6y506JP6qQbOOBb/usuibunodycZqX0p6sKLWxLlrrsY+U/Lg/Yuxljs+oC+ZtNSwUC7SAfGdjr4+AraBdxG3IHXXehwr7ts6l1A7niXr6Sw4l227bUuznuqFT3kTNY66xQkL217yiYqIkdbtZnXV7X3TQb2iS5ZmfJCYpssG+8S9YLffDTOjs98zB+1fUXvqujP4DbiQrv44l10GCJDjyg542WVrRpzweaE6/ku1mmO+4zUfSb1viczLftg1fdNBuRLVQUjsU0Wj9Xda/OyTkvZTMyueL7g9uX6OiniXdIBbU7H3faMUu8zkgXqs/LqlXGP1XVmFyVfYs0L1284QVbzhHM9Q+2YUxCHMHXCmW/UCkqAewlWfga3AVfoMNoBfOpMKHfgdRdoFxVV53Jf4kRRkrkAE0izVGql4PPzsaMXlik+4ZJG3GhCBOsu4NK57LocW2DdhQ6su/jAc56jgYV2CaRPFyU1FAw3GH62VYgTvtQoyydh+RLlcMS7sAXiXe7FvRvupl3oGHu+3FFbuwSySJMvQ9bIU38WjiojtiaC4EBgwaadEUFgbKcD2gXc23EH3jOig9WQXQn1ymjcIx3I3f7V0yZJ86iseBenZNl/arye4cwxYF4vQLvQwcdX0C4tuHcD1l184DBS10Yz7RIlXwL993ISlaJduGmCSxQ0WOK8AG4Ol3vj5gM+dSaUO/C6yz3iXahoo102/9LL5pIvFP3hm0EZtitjPUOWZDFQRMEwrCNwE7i+BuDQLs/3Wz26f73JkfD/4/zjs/rHpxSBI3ZZOtpzaBf+NhvH7Z/UE9QPBCfIm1pi4VzzMOo38FPAk0aN7Bn5vK1OhMRmYMygTDqO74gzjmSTDKeIaeBPu4HR03GOErD56Mux+apdL5yL7LbeEqrjgDCcvhp4z4jYNqo+t40Jot7FGAubG56w02b0WCnQRTSowmX/39iAelAF2Yb7jJiBj6+wv9iCezfcTbvQUel5+axQ/F2MYW542k5ekKArmF4LHr77d9pbUgRGKVr2FIztdPDxFbQLuI24A8e70GFcU46HY+KpAZ92ociXhPotogkqtUl1avfdv5OcbzPYNh9mt5T4fOZj/qjtK3rThXZpwb0bsO7ig32t3NuiYmhwxezrg1WXRjIFQb0xx+fngCBgAoqFsa1I4rwArg1fc3XsFyfbcTdwrm8RXObrLjmgx7uon9lOLbFQC1L1CSIB7VJVvjytMF56ylXXXaZgRAhDBUM0KSHehdVYB24Dbv/W3BIS50WJuNu6S3Lb4Da1xCLB/kp9sLZ8UVMw0ulVd/R8u4uYBANi7eQzp4LbhitvuOwFPnUmlMt83aUjV6KCSba5np+JM2Jy7moiHCor1gBbQHRBpdLlANeldCDeRd76B9o3HRLXXbq3q7QhvjGSp6IDVbXLpT2lfJvvh1I2JBNbomXpEoCxnQ5ol3tpF3C3odddcmDk6xz3eb6GpoUdOnK0i6ERi+RLmaf7ajW5iJjDsv0A7UIHH1/dS7tInNskQuK6Sy8E7vtVwef1v+0ssECZy30WqtzYghDzdeqYjrG6ckEsnepqifMCuDncYWW7E3z8fkMu83WXHNS+tj7kSwMB0T5HOi79TNQuW2TgS1T9+kRMAtLukR4D4dI104jgNub6+gu0C986G54L7ZLD9a2ChGdK52YTJYUpuNLDql2poAuFNoKsoI5xJj6qcNn8pfO5lG2bBDeKC+1SHpzrWwSXuXbhzKVEnwQkyEQWPceoEY6wYeurKH1QSklQ0gl7Ow13W3ep4cMdiAegg4+v7hXvkgOJ5WXFHVi75KCGzU75Yoz1Ozdt9OdcR1ElaqZd7PNLYasY7/JYpnl9VUo8BCPe5dIDmeAzH/MHH19Bu7TIF9wN2qVTvuEg31KjfxvQtYtdqEBMdJF807hFtMsXj0X9YXlki48wfc9ueZiHdkqu7innlmvwmY/5o7av6NV3L+0Cbkcuc+3SC1Vtvry5OmGg7wiir5yFCq9RFcm3MVe3/LXOqo54LAVWTCjaRcn0tc7ToV1yoZauto7hWb/35Pqq7O7xLpzrbHjuwNpFos07oF02ws5RjIaI4xbL15AuHxzi47FM87p+1mXm9XWs0XyFhnWCRt/URZ1vNl/K95TXOivfzQy2xzJdpvbY1c/ycHk1LE0MX0XpGFbjJMoRMyMAACAASURBVLhErphhqwjkzjGykKNdJIJPf47l0q9Ny+ZblRtbqEwB10v/6fm+1tle8nhoSmKXCfvqyPl5/6SccIqMg/5a52/aGmVeX7o8Mr8exMdyyhRfapr9Pq/6FElYm4ZFDPP2DK6Tey/tkgM+dSaUy3zd5bbc8bTLlhQ/m2RRN7ie3vbZs5mmyRIfxgqK/dlcYlkeykFtUef48vn18/2x6BE2Gnd1JuBKzV86DZTVlEsWRfcABhjFuzzfb9Wa/WvtI8f/GikbifuOGJbY/21iSxeNd0TVLg1yjzpo/BRg2SeoH3LsTChvuFzEI/tgUc9m4+DlT0XKa4yAlyzVCcmebHwkcI/0a52nj6BI0C6WntCDgCeXslkWQ4KcCX6N+SKc2hdH6QJ+UBNJaPO2+mFVvwMcSUiBXpv3itXNQa98JcLpK+Z7RrdtV7FLFB1B95V9RX7JDfghzA07sN5Y5xMu27Z5dnDUn4zPwXUXdcPHzOJLOD861l0WNYGr1AilM/2Q3IATFm9uju7j1YF7aRdwO3KZ7xn1QnebBQ3cUb6K1S6bf+eIp3bR1l1e66zqgY8SSNIup7Zwxbts22tdbIoV3nvGu3xlkCvexZmaXbpsX4WRo2BYjbG34soYs0rhbvNiL0hcd8mB9HYlRb400C5OP/AZrw9YESFqsMtkiQ+KdjngO9P43XkHtZWgttyi3lUUSi3hTZOZfoZ2YcKl90EBA5YBzn4HdkC7yOLGjtocbL5E2mwkRcZthU3t9ghdH7q0yQSXiugLgrjQLuPkKxEStQvn/lybO6R22VJndylyB9qlFHL6wt3AZx68V7xLDiSWlxWXebzLndvV2NqlthaBdqmBXtqlcdbiAO3Cpfx0SBmv2XKhXVjlq0LKYJ3gq6NotWNlfKh6n5GIWktDR+2yCXzeTzPUHq/o9X4v7SLRZomQuGfUCxzalZRZsJl22fTZi6F2SYhmFYT2sbrGEXqPYNg2RHNHjnfJAbRLG9xNu/RtV5MfUSlkmtEAydplmqacWJmc9Y96bSP2LmJZaHmPtGe8InUKzjpgbK6AAcsAH9+BG8VlvmeUg142B1TLpYi5Q7zLjmRlRiT2Un771C5Fd9JxNNooWVajXVF8K6svjMSV1+glzk93g8R1Fz59kgLK+kpYxEC7ELlpxAY4ViYuW4IUqAVpuaoUaFfSXVociHe517X13XA37dI439i5yiliArKmhs0duTnzOltBoE7qhnzhaXAAdlM0SlcbYe0izp9VAe0iTwdItLkXoF3q5Zs5P+ULl45IrqNMj/GMd/FZIqhamRh8Wb/NLOEPPvPgvbSLrOvFwbgDx7vkIOHe3dsOpr20S5jLR7uo9jg1QeP1DGeOAfNYjVcHuNUvuDvuNQjebV7sBYnrLjlo065uLly2Ttolk95xrHeqhF1AxAqXHNHjjMtxupTPvGgg0ADY2iyU63P1CNqFs9+BHdAuxbnO4V5iX+jCzZd94iSj4StDvjhlTRgBCULkXlYB53bls7yLzctyci+lpK07A/leilSVG6VoiTb7GsndtYvEfCVConZhPm46uzRnm7lxLyfOZHpmypXg81UpCRLF2ng/QC9nPaAXouqR28lFIC/eRaJ2AXdjH+/CuV3tPT+Nm5PvSFyfD/NTyE+5Bpy+cl4oEztm+82mZqCvfda2hA66YlB1A4eTi3kgmSlxnsiBxPGaFRfaJTnfvds3MIY58rVLmhuPfBNS4N+e7Y5pc0VIkGRE7dvWNoaIqDWMKN1Z9eRLm+lOnp7vN/7w1+Bvmn51t0Hi3zHpdrdE+l8RN45XEeiYMb5iUftR73uKjUqpd/LRAffYF5+HiU7moiLb4Mn+GmhgLvN1lxxUtZnV1V5fZPo5f91lc1VHOFlWfdAJyrpLjXwlcu267mWzxGEhx2bbV8IKv0lo30COdpGIXtpFYl/o2AdLDfdGOjxnkRzt0iZfoVxol2RAuwx4bX0HLvN1F7Zc0df0fLhb0Qfk8J85emkXiYjVLhyqnokZUaDYHBHvkmyHxPEL3I5caJcErvT9CD7cHQVHfOaTB7QLHbHtikPVc7AhFly0y92APSM67rZnlINAu5I4PFVFvu5Jc6mnPWuI4ubkW5xbNt5FIhLK271jShwcytosrPAdcbf+nANoFzrC2qWlJfxRSrvEOtaXL7RLTr6iuUelI96FDrnxLo9lmtdX2q9uvNY5mpOKQDtraYYIQLvQEZ4XGxvDHEXmiYLahZIa//kY2iWNu1c9tAsdOXtGJbVLvN9PdeLiUrWLwo3WDHXa2bUZcvpkuI6y8kW8SxSX0s+52cyZe6D4oM9zFsF9Rg24mVWfnG/U812YgGjzPbRL/HJHlfZNMENcn6zBhXaJ4kK7lOUeqKRduMmXgtql0kN1+TyrN3P9o6AldJR9N1Ab9Hqf0WOZ5nVd9l46r6/n7x/H588pr3WezGPb9ljOTeH9+OPv6a/vCYdkUbXLSVkermSWx6ZpBoN7JGgw1Hx3a4/klZOXxSJ+uUrxNyWZWDM0lXaaodrwcBEdtRCur39+KnX0MFj+9I86usjINti2jW7wBxLnRWgX/twDR5vNT8pIsGCa+Qj7KqAbJhcCr9yjp+wzo/sELHHvZpImXLbSNkdpl+8Ut2uU8/M59X6mwPPja50na2r3zfH7B4VyJK4msz2W5aEvdzgTVPBNRzFRlS6vdZ7Oz4suTL6l+9tR5K2cGX4bLCe7zLBxWV++9BXJFcrINvikPH//mKx0punfNPVyLxwxpOpBbhMhE5TSPbHupeTrm8vZ6rzYF0pHnblFvhCnLzI1cZeuOuq6C71vRq67BCZpdUI+vphrGwTtYioDa2Y/fjnnwYBtBwwjDelizKnEtaJyZjhscJtxIY807qWoCqRP0WG20449wd/fEp4Hp+k/yxRSW/eE895dege+FThrl80jXxhql7AccVICcsQnX8IJOpNl6CsKN7m3It7Fhs+ZOfEuBO2i7x6ZKwxE7aJtZUyTtpZzHtGDTLybNdaSj6IVtBlcnVKdRLd2KWaGaYPXjHLaJZz+VUZugw/t8ucrDVXt8v/DK0X3hPPeXbsDQ81spbUL3Z/hfO2KU1PmMx875QVl5osNTPGt6Fwmy8dXsdy07ilxr8oFaqxqjs0ltcs/f97a8Zh1l1C8i2NS1Mvw+8c0zbMWH0tZB5rX1/Z8v3eLNM1h7Il49JbLZiNM12vGf99v4wTTDHtf5mvG8/1O1i5mHV3551KrnXBsJJVZd5E7fmVyJwvGwUr53oRroODQbyQVK4wqwanVVOFyoOyFu5Gys1VTbI5Fd25CvZfWLvv1vTbEPpbJtWafAGtRYZ7nyJS5ahf1Ov6cF5UZ8vz99c9faiSGP97lCP14LMeR55+f8zzrE+c5kZ4JGpE2X+2yH9eljx66MU+TRfTrLZIZH1+pKx2mGVb4yNf+5/utmlFMu7j8Q9BquqPMeJevdvn9Q2kAh3b5N2XLqPsY1Itrj/KXg353mwVxDVSVF8SpuiqM9bzucoqPJTbKxoC3KZ1fuyiD7OfumRzJoibuS6ekdqE7sKB28dxndMi1ZdHntv28NXyfkaqGvvhrXRfHNb+ZoGLON+u9jaoSwrJy2pdDLJtdc/kj0YzzXM0MfVfMTSynXS7Sv9QutsF6HdlVOf0PpX1LnBcbaJd6+d6EayDg1YLp187FQGDNo5kNYVBadXsUb1cNSufK4rFoM8++L2DMsMpywWZctaqTz/f8xz5JLA/HdOPbDTDSCduccs7nTMpJ3GBrhgaw23cXMxhD3TN62wfxXF0nwmv7rIb47iioe6J8S493cf6UXIMJ5bVjTdKyrgpf8x5AE2+t5ItXu7wMSWErjGPJ/dgVcd3bq243bZvrUjmQsvvu1LI+4diyr9BHM1jtm4d0ORdPVBRZJIwFtEsKLrVLR9u4oUbsan6+4XRy6jG2vKpw2f8nZNoGqsDa5Mfq2qB04QrxLvP6+sqGzwTlWh15rfO0rFqIg3VvrylWrHgXe7XenU7YZipy4l3ujrLafERAu6QgrF06GsYQPLXLJTe5Nousu3BrRfr0p93rxE1/ZHIvu3Ppe6Q1DbEshgTRtIi2/W/LErd2uVp3cacTttmEr8U6+u/z/VaP7l+PP/t49yPHfyb2wGbikWn6Jc7mxn62BzsOFtoHj+OxxKO8YVf4UrMNyCmgMaNUdWabvFQpEHuPT204jTGES6/mHW5XmYk7qyA/Zdct7qe80G+cca+7LK47apypub66Unanc+Kw+dJdpD7lz+gCxhgELrhhLt5nROFGzTRMbBbBdaLIjE5MpI2AsKe07gomYACTh8MWb1dOlK0Cl98UeXHemeuOSvmurDieW/99rHu8dnGnE7Y5HdAu4DbiQrtQuFGjGxObRXCdaKldttKzl43wsnx7BRPOkc/DYdtol62ojgyvu7gOKvcZ6e/xO3TMB+aCjS/xi/uMbFt6vYvx7mjWvgdAjna5G5zapZcxRPTqCxX0NMnbgtbVLlNuo2CIuRi/DqOJw7AVTKym4SP76MiMd3GcWcqygaHGwPN/BTyHZOnapd7zPaXA9hV/7dILlbTLpcMF5Usc+inTZxFEWStRu+Rwa7uXGxKaxAHHOFnMrqGxhxcVn1wrvQK+e7JR6y5FrK2qgaombrSrGgJOrnMM1JhjKONpON9wCuF807jJxgRsKIs0ayXqD+e1RzMkm90FOTaX1C582koD7hTzCvgoINlJ3wFNriPfG+BKWVgvcenpR21jc1vb34vQJQXVhzkGFDGmC5hYG9uuSnWcwH6iDacNuSVvixyboV14zYtIdrJmPob6UrUT6fsSJ4Kndpn6TQOqGzOTkhUGEWVt1ToititiX4jKOjmdvo02DWXLBe1yjUojAofAFA7JGr7N15c1UGkbboz0Ra+7bAymgcz5TwWTu46JoFhbUNv5QNkTLFVBgWQT6PlmtAQX7XIrSGwoUlDEt1WvOEXHo9ROv+W1fiXdc9kCa8S7+NLJnCMFCZfNsja8hxJOqlTbcNZCQcli55KTQil72qCwD0slNDYkNhQpKOVb1FEvNPP82NrFSDBt7hS97mI8XLWqdglrlDb55t+jlEzvghybcZ9RIiQ2FCmAdpGOMbRLWf1Rihs1rWavgbnffVMJzv3iNAGxxaydRLk0Kt9LGBll7o9nVHQHZD7fBbG66XGgCc0aoMDwLepIHKI8zzDeZZPTeCIn4McyqY83vVQktnbZH5OqvaTmm2gBfaNaG6EvSkA1o0GbdGadk6+sBbYd9PAm+zi0C+ZFdijVn1FHvRDl+fG0S8eGdzUxP5Zpnmf1ee1p2kURL691nibH896L2p+JWDNqP1c3x7ZAmrKEy1baZmiXa0hcoJOCUvcZoY56IdbznLVL2tRSdk7KhG7MY5nm9bHOH+lhvHfG/uz5sGpvIP5+V96Po73NxvFqm6/0+drzPaZaW1aORKFBuypehFHXXejg0uWYQ2JDkYJSvkUd9UIzz1fVPYEJRtC1lkO7vI6XCqdql5fzq/324OO9xJv2SuHjvcXmHpZjzTVZuzDUxLWFi6xLtcx4F8eZpSwbG5gU66GUb1FHvdDM89AuYVjTw1dePJZpeWRol6/80NJ5aKsx07IeEmVT9Yr6Rdu0Cqy5JsgXhnV0abb0+4xiH75Asdl3Du4zSgSu6esB6y7ScfN1l/CI3HhO1etCXRoxomvjtMsuP5ZFlSCaEHmtsxbSe+4XfWBrF8taFs93KcWtbTMH7bJF9v0cmxGri1gKXkC8i3SMEe+yZYS8MJlFdugTiaIVHsu0LOnaRQtlca+7LMqOkbZ9dMLULpRpjy5fklG8TRKtFa1dTlW6UPsOtAvuMxoKhm/ta6+0dIBmiPI8W+2yDdGEPOsu2/cGIe3rLi6UaNuQdjmiZiztom4JueJdtu21Ls7HxtCv2tlqFycatKIubXWycNSgcTzZZnq5puf7rdbc/nU/4jve98jxv2XuAwxqjfBYpum7J+668rJx+NZXF6rzA/WFOuqF3fNqvRiTgW9Ucf4U6IzH1zbdnM+gRzzijXfZod0EdG7rKPcRBbXLCVW76JtFWq9X9o20BZvNaW1Hv1HaFT1BtTvUM77xcGerluf7vdfafoItX2wL7YFiswpIOWc/grGeBAnzon6zYh/oI50Wr+fFpW8v5TwxHYCEffpZqNJzk/9c3QO+Zhbmhotf2+YoY7jBFovJSfXiGmjm/8YZqZIlgaUeLGZYqYTGhoAR4bXO8zx3FS+2VqE8epPi24CWj0on+JxQor0X+Dy7a0dnKWmD/nQyqvTcBtIum6cs0C6VMIB2MbhRzk/Ot154n3HrkD3qRtms0jNttvMV08o7gux0X/ibUn92sL3x8IPzPJv45a7HYu85C+03Euz/NXvMk70paKzHMQP7g/vMRPTMN++xBN9OLjjP8Wd1WK76s/BzQo27Lc4IASEw5ApRyjWbL3lqlyL5luJCu3Tkxjo/J996N/fZISzqr8ltclKCYy5Pto+X1C4c2kozLq2h+G5B/OI7M5ghbctDn/W+kW0WUdtPNp+g8L2VUXt9yaTwFC1lHjRK4dyfNj5bZrgv06/Ey9V9kpsu/31BYXH60v2c0KOMvkeFXj0nVAtPtDJVHieqLM4Q7vuwhaYqa80lJP38h0u5egtoVdZ17Y1zn9EOWXO/DVn2M7G2oHZplu+kr2SUgjHM2ick23ykTDmNki+0Cwk0hRuc6dW56hQvqnTxyAhtkvNk8Xlm1KYrCNMGa9XHeSPj5UMgPJ9PG8zkwhsPTkViwBfNfmCL05dGKKIdmWg/KpTwnFDvMoV+mur286N/0c4QmlpTeSz29pdy94glcwMFdKpPgniJvAQUoV2i5gMmE/Am7UkBfKwt0q4aN4Pw6kgC7MHWCT5rRdAuJGSsu6iLG9ZdhcfU4FARTqJbQGjbS5M6Mdq3RDoPXpaC8DlVu1wKF7VHXZ5zhYf/OaF6uYxHhRKeExrULsb9HfZzMPzrLobQNJ8C5svoKkH7Waiuqrqsvi3yubrMtcsWOQnxmYB3yHpCIxNrS2mX/ESIuIxKiYJvCHXWS84cGk6ZeM4BFpcLzJEV72JOVNql+3lV6wxzdRB9E5LKPb4KWHch+rb0uovzOaFGuXSRYMrDC+2i79UEJI5TBjntUZqIYow/NvoyQdezUJO0y**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**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)
![](http://www.bkjia.com/uploads/allimg/160407/114S254T-0.png)
读取mix文件的函数位于Firmware/src/modules/systemlib/mixwr/mixer_load.c中的函数:
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>int load_mixer_file(const char *fname, char *buf, unsigned maxlen) </li></ol>
登录后复制
参数fname为mix文件在系统中的位置,buf为读取文件数据存放的缓冲区,maxlen为buf的最大长度。
该函数会剔除符合下面任何一条的行:
1.行长度小于2个字符的行
2.行的首字符不是大写字母的行
3.第二个字符不是':'的行
剔除这些非法内容的数据后,剩余的全部为格式化的内容,会被全部存入buf缓冲区中。
所以这要求在写mix文件时要遵循mix和格式。
这些格式化的mix内容被读取缓冲区后,就会通过函数
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>int ret = ioctl(dev, MIXERIOCLOADBUF, (unsigned long)buf); </li></ol>
登录后复制
来交给具体的设备处理。
相关结构的定义:
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>/** simple channel scaler */<br /> </li><li>struct mixer_scaler_s {<br /></li><li>floatnegative_scale;//负向缩放, MIX文件中 O: 后面的第1个整数/10000.0f<br /></li><li>floatpositive_scale;//正向缩放, MIX文件中 O: 后面的第2个整数/10000.0f<br /></li><li>floatoffset; //偏移 , MIX文件中 O: 后面的第3个整数/10000.0f<br /></li><li>floatmin_output;//最小输出值 , MIX文件中 O: 后面的第4个整数/10000.0f<br /></li><li>floatmax_output;//最大输出值 , MIX文件中 O: 后面的第5个整数/10000.0f<br /></li><li>};//该结构定义了单个控制量的结构<br /></li><li><br /></li><li>/** mixer input */<br /></li><li>struct mixer_control_s {<br /></li><li>uint8_tcontrol_group;/**< group from which the input reads */<br /></li><li>uint8_tcontrol_index;/**< index within the control group */<br /></li><li>struct mixer_scaler_s scaler;/**< scaling applied to the input before use */<br /></li><li>};//定义输入量的结构<br /></li><li><br /></li><li>/** simple mixer */<br /></li><li>struct mixer_simple_s {<br /></li><li>uint8_tcontrol_count;/**< number of inputs */<br /></li><li>struct mixer_scaler_soutput_scaler;/**< scaling for the output */<br /></li><li>struct mixer_control_scontrols[0];/**< actual size of the array is set by control_count */<br /></li><li>};//定义了一个控制实体的控制体,包括输入的信号数量,输入信号控制集,输出信号控制。 </li><li>//因为一个mixer只有一个输出,可以有0到多个输入,所以control_count指明了这个mixer所需要的输入信号数量,而具体的信号都存放在数组controls[0]中。 </li><li>//输出则由output_scaler来控制. </li><li>//从这些结构体的定义,可以对照起来mix文件语法的定义.<br /> </li></ol>
登录后复制
uavcan_main.cpp:
该文件中有解析上面提到的缓冲数据
- int UavcanNode::ioctl(file *filp, int cmd, unsigned long arg)
- {
- ...
- case MIXERIOCLOADBUF: {
const char *buf = (const char *)arg;
unsigned buflen = strnlen(buf, 1024);
if (_mixers == nullptr) {
_mixers = new MixerGroup(control_callback, (uintptr_t)_controls);
}
if (_mixers == nullptr) {
_groups_required = 0;
ret = -ENOMEM;
} else {
ret = _mixers->load_from_buf(buf, buflen);//这里开始解析数据
if (ret != 0) {
warnx("mixer load failed with %d", ret);
delete _mixers;
_mixers = nullptr;
_groups_required = 0;
ret = -EINVAL;
} else {
_mixers->groups_required(_groups_required);
}
}
break;
}
...
- }
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>int MixerGroup::load_from_buf(const char *buf, unsigned &buflen)<br /></li><li>{<br /></li><li>int ret = -1;<br /></li><li>const char *end = buf + buflen;<br /></li><li><br /></li><li>/*<br /></li><li> * Loop until either we have emptied the buffer, or we have failed to<br /></li><li> * allocate something when we expected to.<br /></li><li> */<br /></li><li>while (buflen > 0) {<br /></li><li>Mixer *m = nullptr;<br /></li><li>const char *p = end - buflen;<br /></li><li>unsigned resid = buflen;<br /></li><li><br /></li><li>/*<br /></li><li> * Use the next character as a hint to decide which mixer class to construct.<br /></li><li> */<br /></li><li>switch (*p) {//首先看该行的第一个字母,来确定数据的类别.<br /></li><li>case 'Z':<br /></li><li>m = NullMixer::from_text(p, resid);<br /></li><li>break;<br /></li><li><br /></li><li>case 'M':<br /></li><li>m = SimpleMixer::from_text(_control_cb, _cb_handle, p, resid);<br /></li><li>break;<br /></li><li><br /></li><li>case 'R':<br /></li><li>m = MultirotorMixer::from_text(_control_cb, _cb_handle, p, resid);<br /></li><li>break;<br /></li><li><br /></li><li>default:<br /></li><li>/* it's probably junk or whitespace, skip a byte and retry */<br /></li><li>buflen--;<br /></li><li>continue;<br /></li><li>}<br /></li><li><br /></li><li>/*<br /></li><li> * If we constructed something, add it to the group.<br /></li><li> */<br /></li><li>if (m != nullptr) {<br /></li><li>add_mixer(m);<br /></li><li><br /></li><li>/* we constructed something */<br /></li><li>ret = 0;<br /></li><li><br /></li><li>/* only adjust buflen if parsing was successful */<br /></li><li>buflen = resid;<br /></li><li>debug("SUCCESS - buflen: %d", buflen);<br /></li><li><br /></li><li>} else {<br /></li><li><br /></li><li>/*<br /></li><li> * There is data in the buffer that we expected to parse, but it didn't,<br /></li><li> * so give up for now.<br /></li><li> */<br /></li><li>break;<br /></li><li>}<br /></li><li>}<br /></li><li><br /></li><li>/* nothing more in the buffer for us now */<br /></li><li>return ret;<br /></li><li>} </li></ol>
登录后复制
下面这个函数用来 处理 M: 开头的定义, 格式规定该字符后面只能有一个数字,用来指明input信号源的数量,即S类型数量的数量,联系到结构体的定义,则为 struct mixer_control_s 的数量.
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>SimpleMixer *<br /> </li><li>SimpleMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf, unsigned &buflen)<br /></li><li>{<br /></li><li>SimpleMixer *sm = nullptr;<br /></li><li>mixer_simple_s *mixinfo = nullptr;<br /></li><li>unsigned inputs;<br /></li><li>int used;<br /></li><li>const char *end = buf + buflen;<br /></li><li><br /></li><li>/* get the base info for the mixer */<br /></li><li>if (sscanf(buf, "M: %u%n", &inputs, &used) != 1) {<br /></li><li>debug("simple parse failed on '%s'", buf);<br /></li><li>goto out;<br /></li><li>}//复制M:后面第一个数值到无符号整型数据到变量inputs中,并将已经处理的字条数目赋值给used<br /></li><li><br /></li><li>buf = skipline(buf, buflen);//让buf指定下一行<br /></li><li><br /></li><li>if (buf == nullptr) {<br /></li><li>debug("no line ending, line is incomplete");<br /></li><li>goto out;<br /></li><li>}<br /></li><li><br /></li><li>mixinfo = (mixer_simple_s *)malloc(MIXER_SIMPLE_SIZE(inputs)); </li><li> //M:后面的数字为struct mixer_control_s 结构的数量.MIXER_SIMPLE_SIZE的字义为sizeof(mixer_simple_s) + inputs*sizeof(mixer_control_s), </li><li> //即一个完整的mixer_simple_s的定义,controls[0]一共有inputs个.<br /> </li><li><br /></li><li>if (mixinfo == nullptr) {<br /></li><li>debug("could not allocate memory for mixer info");<br /></li><li>goto out;<br /></li><li>}<br /></li><li><br /></li><li>mixinfo->control_count = inputs;//input 信号的数量<br /></li><li><br /></li><li>if (parse_output_scaler(end - buflen, buflen, mixinfo->output_scaler)) {<br /></li><li>debug("simple mixer parser failed parsing out scaler tag, ret: '%s'", buf);<br /></li><li>goto out;<br /></li><li>}//该函数解析输出域,并将期填充到mixinfo的output_scaler字段中.<br /><p></p><pre class="code"><ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>int SimpleMixer::parse_output_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler)<br /></li><li>{<br /></li><li>int ret;<br /></li><li>int s[5];<br /></li><li>int n = -1;<br /></li><li><br /></li><li>buf = findtag(buf, buflen, 'O');//寻找"O:"这样的控制符,返回指针指向输出格式域定义的首字符'O'.<br /></li></ol>
登录后复制
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>if ((buf == nullptr) || (buflen < 12)) {<br /></li><li>debug("output parser failed finding tag, ret: '%s'", buf);<br /></li><li>return -1;<br /></li><li>}//12,表示O:这行的定义至少有12个字符(O:和五个1位长的整数),例如最短的定义为: O: 0 0 0 0 0<br /></li><li><br /></li><li>if ((ret = sscanf(buf, "O: %d %d %d %d %d %n",//O:后面必须有5个整数,且整数间用至少一个空格分开,此处是取出O:后面的5个整数值.<br /></li><li> &s[0], &s[1], &s[2], &s[3], &s[4], &n)) != 5) {<br /></li><li>debug("out scaler parse failed on '%s' (got %d, consumed %d)", buf, ret, n);<br /></li><li>return -1;<br /></li><li>}<br /></li><li><br /></li><li>buf = skipline(buf, buflen);<br /></li><li><br /></li><li>if (buf == nullptr) {<br /></li><li>debug("no line ending, line is incomplete");<br /></li><li>return -1;<br /></li><li>}<br /></li><li> //从下面的赋值操作可以得出 O:后面5个数值的字义.,分别为 [negative_scale] [positive_scale] [offset] [min_output] [max_output] </li><li> //并且每个这都做了除10000的操作,所以MIX格式定义中说这些值都是被放大10000倍后的数值.<br /> </li><li>scaler.negative_scale= s[0] / 10000.0f;<br /></li><li>scaler.positive_scale= s[1] / 10000.0f;<br /></li><li>scaler.offset= s[2] / 10000.0f;<br /></li><li>scaler.min_output= s[3] / 10000.0f;<br /></li><li>scaler.max_output= s[4] / 10000.0f;<br /></li><li><br /></li><li>return 0;<br /></li><li>} </li></ol>
登录后复制
//上面解析了MIXER的输出量,下面开始解析输入量,因为我们已经读取了输入信号的数量("M: n"中n定义的数值),所以要循环n次.
//首先记住parse_control_scaler函数输入的参数
for (unsigned i = 0; i < inputs; i++) {
if (parse_control_scaler(end - buflen, buflen,
mixinfo->controls[i].scaler,
mixinfo->controls[i].control_group,
mixinfo->controls[i].control_index)) {
debug("simple mixer parser failed parsing ctrl scaler tag, ret: '%s'", buf);
goto out;
}
}
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>int SimpleMixer::parse_control_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler, uint8_t &control_group,<br /></li><li> uint8_t &control_index)<br /></li><li>{<br /></li><li>unsigned u[2];<br /></li><li>int s[5];<br /></li><li><br /></li><li>buf = findtag(buf, buflen, 'S');//找到剩余缓冲区中的第一个'S',并让buf指向该行的行首; </li><li> //<br /> </li><li> //16表示该S:行至少有16个字符,即至少有7个整数(因为整数间至少有1个空格分隔)<br /></li><li>if ((buf == nullptr) || (buflen < 16)) {<br /></li><li>debug("control parser failed finding tag, ret: '%s'", buf);<br /></li><li>return -1;<br /></li><li>}<br /></li><li> //读取S:后面的7个整数.<br /></li><li>if (sscanf(buf, "S: %u %u %d %d %d %d %d",<br /></li><li> &u[0], &u[1], &s[0], &s[1], &s[2], &s[3], &s[4]) != 7) {<br /></li><li>debug("control parse failed on '%s'", buf);<br /></li><li>return -1;<br /></li><li>}<br /></li><li><br /></li><li>buf = skipline(buf, buflen);<br /></li><li><br /></li><li>if (buf == nullptr) {<br /></li><li>debug("no line ending, line is incomplete");<br /></li><li>return -1;<br /></li><li>} </li><li><br /> </li><li> //从下面的赋值可以看出MIXER文件S:定义的格式,S:后面的整数分别为 </li><li> // [control_group] [ontrol_index] [negative_scale] [positive_scale] [offset] [min_output] [max_output]<br /> </li><li> // 可以看出,输入信号的定义比输入出信号的定义多了两个整数,用来表示当前输入信号所在的组和组内的序号. 第1和第2个整就是用来 </li><li> // 说明组号和组内序号.而后面5个整数的定义和输入信号的定义一样,且也要除以10000.<br /> </li><li>control_group= u[0];<br /></li><li>control_index= u[1];<br /></li><li>scaler.negative_scale= s[0] / 10000.0f;<br /></li><li>scaler.positive_scale= s[1] / 10000.0f;<br /></li><li>scaler.offset= s[2] / 10000.0f;<br /></li><li>scaler.min_output= s[3] / 10000.0f;<br /></li><li>scaler.max_output= s[4] / 10000.0f;<br /></li><li><br /></li><li>return 0;<br /></li><li>} </li></ol>
登录后复制
sm = new SimpleMixer(control_cb, cb_handle, mixinfo);
if (sm != nullptr) {
mixinfo = nullptr;
debug("loaded mixer with %d input(s)", inputs);
} else {
debug("could not allocate memory for mixer");
}
out:
if (mixinfo != nullptr) {
free(mixinfo);
}
return sm;
}
http://www.bkjia.com/PHPjc/1117247.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1117247.htmlTechArticlemixer 结构分析[uavcan为例] mixer指令为系统的app命令,位置在Firmware/src/systemcmds/mixer目录下面,其功能是装载mix文件中的有效内容到具体的设备...