Home > Article > Backend Development > mixer 结构分析[uavcan为例]_PHP教程
<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的最大长度。
<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>
<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>
<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>
<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>