示例#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
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();
}
int STDMIX_GetMixers(struct Mixer **mixers, u8 dest_channel, int count)
{
    u8 idx;
    u8 i = 0;
    struct Mixer *mix = MIXER_GetAllMixers();
    for (idx = 0; idx < NUM_MIXERS; idx++) {
        if (i >= count)
            break;
        if (mix[idx].src!= 0 && mix[idx].dest == dest_channel) {
            mixers[i++] = &mix[idx];
        }
    }
    while(i < count)
        mixers[--count] = 0;
    return i;
}
示例#4
0
s16 eval_chan_cb(void * data)
{
    (void)data;
    int i;
    struct Mixer *mix = MIXER_GetAllMixers();
    for (i = 0; i < NUM_MIXERS; i++) {
        if(MIXER_SRC(mix->src) != 0 && mix->dest != mp->cur_mixer->dest)
            MIXER_ApplyMixer(mix, mp->raw, NULL);
    }
    for (i = 0; i < mp->num_mixers; i++)
        MIXER_ApplyMixer(&mp->mixer[i], mp->raw, NULL);
    s16 value = MIXER_ApplyLimits(mp->cur_mixer->dest, &mp->limit, mp->raw, NULL, APPLY_ALL);
    if (value > CHAN_MAX_VALUE)
        return CHAN_MAX_VALUE;
    if (value < CHAN_MIN_VALUE)
        return CHAN_MIN_VALUE;
    return value;
}
示例#5
0
static void _show_page()
{
    u8 h = 12;
    int i;
    PAGE_RemoveAllObjects();
    PAGE_ShowHeader(_tr("Mixer"));
    memset(gui, 0, sizeof(*gui));

    struct Mixer *mix = MIXER_GetAllMixers();
    u8 space = ITEM_HEIGHT + 1;
    u8 row = space;
    u8 w1 = 50;
    u8 w2 = LCD_WIDTH - w1 - ARROW_WIDTH - 4;
    for (i = 0; row < space * 5; i++) {
        u8 idx;
        labelDesc.style = LABEL_LEFT;
        u8 ch = mp->top_channel + i;
        if (ch >= Model.num_channels)
            ch += (NUM_OUT_CHANNELS - Model.num_channels);
        if (ch < NUM_OUT_CHANNELS) {
            GUI_CreateButtonPlateText(&gui->limit[i], 0, row, w1, h,&labelDesc, MIXPAGE_ChanNameProtoCB, 0,
                    limitselect_cb, (void *)((long)ch));
        } else if(! _is_virt_cyclic(ch)) {
            GUI_CreateButtonPlateText(&gui->limit[i], 0, row, w1, h,&labelDesc, MIXPAGE_ChanNameProtoCB, 0,
                    virtname_cb, (void *)((long)ch));
        } else {
            GUI_CreateLabelBox(&gui->name[i], 0, row, w1, h, &labelDesc,
                                   MIXPAGE_ChanNameProtoCB, NULL, (const void *)((long)ch));
        }

        labelDesc.style = LABEL_CENTER;
        GUI_CreateButtonPlateText(&gui->tmpl[i], w1 + 2, row, w2, h , &labelDesc, template_name_cb, 0,
                templateselect_cb, (void *)((long)ch));

        row += space; // bug fix: dynamically showing/hiding items won't work in devo10, it causes crash when changing template from none to simple/expo/complex
        for (idx = 0; idx < NUM_MIXERS; idx++)
            if (mix[idx].src && mix[idx].dest == ch)
                break;
        if (idx != NUM_MIXERS) {
            enum TemplateType template = MIXER_GetTemplate(ch);
            labelDesc.style = LABEL_LEFTCENTER;
            GUI_CreateLabelBox(&gui->src[i], 0, row, w1, h, &labelDesc, show_source, NULL, &mix[idx].src);
            if (template == MIXERTEMPLATE_EXPO_DR) {
示例#6
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;
}
示例#7
0
static void _show_page()
{
    // Note for future maintenance: DO NOT use logical view to draw all the channel items at a time for this page:  I just
    // gave it a try, it spent very long time to construct all the 30 items and could trigger watch-dog to reboot !!!
    static const int XOFFSET = ((LCD_WIDTH - 320) / 2);
    int init_y = LCD_HEIGHT == 240 ? 44 : 36;
    int i;
    if (mp->firstObj) {
        GUI_RemoveHierObjects(mp->firstObj);
        mp->firstObj = NULL;
    }
    struct Mixer *mix = MIXER_GetAllMixers();
    for (i = 0; i < ENTRIES_PER_PAGE; i++) {
        guiObject_t *obj;
        u8 idx;
        int row = init_y + 24 * i;
        u8 ch = mp->top_channel + i;
        if (ch >= Model.num_channels)
            ch += (NUM_OUT_CHANNELS - Model.num_channels);
        if (ch < NUM_OUT_CHANNELS) {
            obj = GUI_CreateButton(&gui->name[i].but, XOFFSET+4, row, BUTTON_64x16, MIXPAGE_ChanNameProtoCB,
                                   0x0000, limitselect_cb, (void *)((long)ch));
        } else if(! _is_virt_cyclic(ch)) {
            obj = GUI_CreateButton(&gui->name[i].but, XOFFSET+4, row, BUTTON_64x16, MIXPAGE_ChanNameProtoCB,
                                   0x0000, virtname_cb, (void *)(long)ch);
        } else {
            obj = GUI_CreateLabelBox(&gui->name[i].lbl, XOFFSET+4, row, 64, 16, &DEFAULT_FONT,
                                   MIXPAGE_ChanNameProtoCB, NULL, (void *)((long)ch));
        }
        if (! mp->firstObj)
            mp->firstObj = obj;
        GUI_CreateButton(&gui->tmpl[i], XOFFSET+132, row, BUTTON_64x16, template_name_cb, 0x0000,
                         templateselect_cb, (void *)((long)ch));
        for (idx = 0; idx < NUM_MIXERS; idx++)
            if (mix[idx].src && mix[idx].dest == ch)
                break;
        if (idx != NUM_MIXERS) {
            enum TemplateType template = MIXER_GetTemplate(ch);
            GUI_CreateLabelBox(&gui->src[i], XOFFSET+68, row, 60, 16, &NARROW_FONT, show_source, NULL, &mix[idx].src);
            if (template == MIXERTEMPLATE_EXPO_DR) {
示例#8
0
static int row_cb(int absrow, int relrow, int y, void *data)
{
    (void)data;
    u8 idx;
    struct Mixer *mix = MIXER_GetAllMixers();

    int selectable = 2;
    int channel = absrow;
    if (channel >= Model.num_channels)
        channel += (NUM_OUT_CHANNELS - Model.num_channels);
    if (channel < NUM_OUT_CHANNELS) {
        labelDesc.style = LABEL_LEFT;
        GUI_CreateButtonPlateText(&gui->limit[relrow], COL1_X, y, COL1_W, LINE_HEIGHT, &labelDesc, MIXPAGE_ChanNameProtoCB, 0,
                                  limitselect_cb, (void *)((long)channel));
    } else if(! _is_virt_cyclic(channel)) {
        GUI_CreateButtonPlateText(&gui->limit[relrow], COL1_X, y, COL1_W, LINE_HEIGHT, &labelDesc, MIXPAGE_ChanNameProtoCB, 0,
                                  virtname_cb, (void *)((long)channel));
    } else {
        GUI_CreateLabelBox(&gui->name[relrow], COL1_X, y, COL1_W, LINE_HEIGHT, &labelDesc,
                           MIXPAGE_ChanNameProtoCB, NULL, (const void *)((long)channel));
        selectable = 1;
    }
    labelDesc.style = LABEL_CENTER;
    GUI_CreateButtonPlateText(&gui->tmpl[relrow], COL2_X, y, COL2_W, LINE_HEIGHT , &labelDesc, template_name_cb, 0,
                              templateselect_cb, (void *)((long)channel));

    for (idx = 0; idx < NUM_MIXERS; idx++)
        if (mix[idx].src && mix[idx].dest == channel)
            break;
    if (idx != NUM_MIXERS) {
        // don't show source if curve type is fixed, works only for the first mix per channel
        if(CURVE_TYPE(&mix[idx].curve) != CURVE_FIXED) {
            labelDesc.style = LABEL_LEFT;
            GUI_CreateLabelBox(&gui->src[relrow], COL3_X, y, COL3_W , LINE_HEIGHT, &labelDesc, show_source, NULL, &mix[idx].src);
        }
    }
    return selectable;
}