示例#1
0
void STDMIXER_InitSwitches()
{
    struct Mixer *mix = MIXER_GetAllMixers();

    if (Model.limits[mapped_std_channels.throttle].safetysw)
        mapped_std_channels.switches[SWITCHFUNC_HOLD] =  MIXER_SRC(Model.limits[mapped_std_channels.throttle].safetysw);
    unsigned found_gyro_switch = 0;
    unsigned found_flymode_switch = 0;
    unsigned found_drexp_rud_switch = 0;
    unsigned found_drexp_ail_switch = 0;
    unsigned found_drexp_ele_switch = 0;
    for (unsigned idx = 0; idx < NUM_MIXERS; idx++) {
        if (!MIXER_SRC(mix[idx].src) || MIXER_MUX(&mix[idx]) != MUX_REPLACE)  // all none replace mux will be considered as program mix in the Standard mode
            continue;
        if (!found_gyro_switch && mix[idx].sw != 0 && (mix[idx].dest == mapped_std_channels.gear || mix[idx].dest == mapped_std_channels.aux2)) {
            found_gyro_switch = 1;
            mapped_std_channels.switches[SWITCHFUNC_GYROSENSE] = mix[idx].sw;
        } else if (!found_drexp_rud_switch && mix[idx].dest == mapped_std_channels.rudd && mix[idx].sw != 0) {
            found_drexp_rud_switch = 1;
            mapped_std_channels.switches[SWITCHFUNC_DREXP_RUD] = mix[idx].sw;
        } else if (!found_drexp_ail_switch && mix[idx].dest == mapped_std_channels.aile && mix[idx].sw != 0) {
            found_drexp_ail_switch = 1;
            mapped_std_channels.switches[SWITCHFUNC_DREXP_AIL] = mix[idx].sw;
        } else if (!found_drexp_ele_switch && mix[idx].dest == mapped_std_channels.elev && mix[idx].sw != 0) {
            found_drexp_ele_switch = 1;
            mapped_std_channels.switches[SWITCHFUNC_DREXP_ELE] = mix[idx].sw;
        } else if (!found_flymode_switch && (mix[idx].dest == NUM_OUT_CHANNELS + 2) && mix[idx].sw != 0) { //virt3
            found_flymode_switch = 1;
            mapped_std_channels.switches[SWITCHFUNC_FLYMODE] = mix[idx].sw;
        }
        if (found_flymode_switch && found_gyro_switch && found_drexp_rud_switch && found_drexp_ail_switch && found_drexp_ele_switch)
            break;  // don't need to check the rest
    }
}
示例#2
0
const char *set_mux_cb(guiObject_t *obj, int dir, void *data)
{
    (void)obj;
    (void)data;
    u8 changed;
    u8 mux = MIXER_MUX(mp->cur_mixer);
    mux = GUI_TextSelectHelper(mux, MUX_REPLACE, MUX_LAST-1, dir, 1, 1, &changed);
    if (changed) {
        MIXER_SET_MUX(mp->cur_mixer, mux);
        MIXPAGE_RedrawGraphs();
        sync_mixers();
    }
    switch(mux) {
    case MUX_REPLACE:
        return _tr("replace");
    case MUX_MULTIPLY:
        return _tr("mult");
    case MUX_ADD:
        return _tr("add");
    case MUX_MAX:
        return _tr("max");
    case MUX_MIN:
        return _tr("min");
    case MUX_DELAY:
        return _tr("delay");
    case MUX_LAST:
        break;
    }
    return "";
}
示例#3
0
void STDMIXER_SetChannelOrderByProtocol()
{
    const u8 *ch_map = CurrentProtocolChannelMap;
    if (! ch_map) {
        // for none protocol, assign any channel to thr is fine
        ch_map = EATRG0;
    }
    CLOCK_ResetWatchdog();// this function might be invoked after loading from template/model file, so feeding the dog in the middle
    unsigned safetysw = 0;
    s8 safetyval = 0;
    for (unsigned ch = 0; ch < 3; ch++) {  // only the first 3 channels need to check
        if (Model.limits[ch].safetysw) {
            safetysw = Model.limits[ch].safetysw;
            safetyval = Model.limits[ch].safetyval;
        }
        if (ch_map[ch] == INP_THROTTLE)
            mapped_std_channels.throttle = ch;
        else if (ch_map[ch] == INP_AILERON)
            mapped_std_channels.actual_aile = mapped_std_channels.aile = ch;
        else if (ch_map[ch] == INP_ELEVATOR)
            mapped_std_channels.actual_elev = mapped_std_channels.elev = ch;
    }
    Model.limits[mapped_std_channels.throttle].safetysw = safetysw;
    Model.limits[mapped_std_channels.throttle].safetyval = safetyval;
    Model.limits[mapped_std_channels.aile].safetysw = 0;
    Model.limits[mapped_std_channels.elev].safetysw = 0;
    Model.limits[mapped_std_channels.aile].safetyval = 0;
    Model.limits[mapped_std_channels.elev].safetyval = 0;

    //printf("thro: %d, aile: %d, elev: %d\n\n", mapped_std_channels.throttle, mapped_std_channels.aile, mapped_std_channels.elev);
    MIXER_SetTemplate(mapped_std_channels.throttle, MIXERTEMPLATE_COMPLEX);
    MIXER_SetTemplate(mapped_std_channels.aile, MIXERTEMPLATE_CYC1);
    MIXER_SetTemplate(mapped_std_channels.elev, MIXERTEMPLATE_CYC2);

    struct Mixer *mix = MIXER_GetAllMixers();
    for (unsigned idx = 0; idx < NUM_MIXERS; idx++) {
        if (mix[idx].src ==0)
            continue;
        if (mix[idx].dest == NUM_OUT_CHANNELS + 9)
           mix[idx].src = 0; // remove all mixers pointing to Virt10, because the Virt10 is reserved in Standard mode
        else if (MIXER_MUX(&mix[idx]) == MUX_REPLACE && mix[idx].src== INP_THROTTLE && mix[idx].dest < NUM_OUT_CHANNELS) { // src=THR && dest = virt should be pitch's mixer
            mix[idx].dest = mapped_std_channels.throttle;
        }
    }
    MIXER_SetTemplate(NUM_OUT_CHANNELS + 9, MIXERTEMPLATE_NONE);// remove all mixers pointing to Virt10 as the Virt10 is reserved in Standard mode
    mapped_std_channels.aile = NUM_OUT_CHANNELS; // virt 1
    mapped_std_channels.elev = NUM_OUT_CHANNELS +1; // virt 2

    // Simplfied timer sw, only throttle channel output is possible to be selected
    for (unsigned i = 0; i < NUM_TIMERS; i++) {
        if (Model.timer[i].src)
            Model.timer[i].src = mapped_std_channels.throttle + NUM_INPUTS +1;
        TIMER_Reset(i);
    }
    CLOCK_ResetWatchdog();
}
示例#4
0
// Roughly verify if current model is a valid simple model
unsigned STDMIXER_ValidateTraditionModel()
{
    struct Mixer *mix = MIXER_GetAllMixers();
    unsigned thro_mixer_count = 0;
    unsigned pit_mixer_count = 0;
    unsigned drexp_mixer_count = 0;
    unsigned gryo_mixer_count = 0;
    for (unsigned idx = 0; idx < NUM_MIXERS; idx++) {
        if (mix[idx].src == 0  || MIXER_MUX(&mix[idx]) != MUX_REPLACE)  // all none replace mux will be considered as program mix in the Standard mode
            continue;
        if (mix[idx].dest == NUM_OUT_CHANNELS + 9) //mixers pointing to Virt10 as the Virt10 is reserved in Standard mode
            return 0;
        if (mix[idx].dest == mapped_std_channels.pitch)
            pit_mixer_count++;
        else if (mix[idx].dest == mapped_std_channels.throttle)
            thro_mixer_count++;
        else if (mix[idx].dest == mapped_std_channels.gear
                || mix[idx].dest == mapped_std_channels.aux2)
            gryo_mixer_count++;
        else if (mix[idx].dest == mapped_std_channels.aile ||
                mix[idx].dest == mapped_std_channels.elev ||
                mix[idx].dest == mapped_std_channels.rudd)
            drexp_mixer_count++;
    }
    if (thro_mixer_count != THROTTLEMIXER_COUNT ||
            (pit_mixer_count != PITCHMIXER_COUNT && pit_mixer_count != PITCHMIXER_COUNT -1) ||
            gryo_mixer_count < GYROMIXER_COUNT || drexp_mixer_count != DREXPMIXER_COUNT *3)
        return 0;

    unsigned cyc_template_count = 0;
    for (unsigned ch = 0; ch < NUM_OUT_CHANNELS; ch++) {
        switch(Model.templates[ch]) {
        case MIXERTEMPLATE_CYC1:
        case MIXERTEMPLATE_CYC2:
        case MIXERTEMPLATE_CYC3:
            cyc_template_count++;
            break;
        }
    }
    if (cyc_template_count != 3)
        return 0;
    return 1;
}
示例#5
0
void MIXER_ApplyMixer(struct Mixer *mixer, volatile s32 *raw, s32 *orig_value)
{
    s32 value;
    if (! MIXER_SRC(mixer->src))
        return;
    if (! switch_is_on(mixer->sw, raw)) {
        // Switch is off, so this mixer is not active
        return;
    }
    //1st: Get source value with trim
    value = raw[MIXER_SRC(mixer->src)];
    //Invert if necessary
    if (MIXER_SRC_IS_INV(mixer->src))
        value = - value;

    //2nd: apply curve
    value = CURVE_Evaluate(value, &mixer->curve);

    //3rd: apply scalar and offset
    value = value * mixer->scalar / 100 + PCT_TO_RANGE(mixer->offset);

    //4th: multiplex result
    switch(MIXER_MUX(mixer)) {
    case MUX_REPLACE:
        break;
    case MUX_MULTIPLY:
        value = raw[mixer->dest + NUM_INPUTS + 1] * value / CHAN_MAX_VALUE;
        break;
    case MUX_ADD:
        value = raw[mixer->dest + NUM_INPUTS + 1] + value;
        break;
    case MUX_MAX:
        value = raw[mixer->dest + NUM_INPUTS + 1] > value
                  ? raw[mixer->dest + NUM_INPUTS + 1]
                  : value;
        break;
    case MUX_MIN:
        value = raw[mixer->dest + NUM_INPUTS + 1] < value
                  ? raw[mixer->dest + NUM_INPUTS + 1]
                  : value;
        break;
    case MUX_DELAY:
        {
            //value initially represents 20ths of seconds to cover 60-degrees
            //convert value to represent #msecs to cover 60-degrees (zero->full)
            if (value == 0 || orig_value == NULL) {
                value = raw[mixer->dest + NUM_INPUTS + 1];
                break;
            }
            value = abs(RANGE_TO_PCT(value)) * 50;
            //rate represents the maximum travel per iteration (once per MEDIUM_PRIORITY_MSEC)
            s32 rate = CHAN_MAX_VALUE * MEDIUM_PRIORITY_MSEC / value;

            value = raw[mixer->dest + NUM_INPUTS + 1];
            if (value - *orig_value > rate)
                value = *orig_value + rate;
            else if(value - *orig_value < -rate)
                value = *orig_value - rate;
        }
    case MUX_LAST: break;
    }

    //5th: apply trim
    if (MIXER_APPLY_TRIM(mixer))
        value = value + (MIXER_SRC_IS_INV(mixer->src) ? -1 : 1) * get_trim(MIXER_SRC(mixer->src));

    //Ensure we don't overflow
    if (value > INT16_MAX)
        value = INT16_MAX;
    else if (value < INT16_MIN)
        value = INT16_MIN;

    raw[mixer->dest + NUM_INPUTS + 1] = value;
}