Exemplo n.º 1
0
const char *set_source_cb(guiObject_t *obj, int dir, void *data)
{
    (void) obj;
    u8 *source = (u8 *)data;
    if (!GUI_IsTextSelectEnabled(obj) ) {
        strcpy(mp->tmpstr, _tr("None"));
        return mp->tmpstr;
    }
    u8 is_neg = MIXER_SRC_IS_INV(*source);
    u8 changed;
    *source = GUI_TextSelectHelper(MIXER_SRC(*source), 1, NUM_SOURCES, dir, 1, 1, &changed);
    MIXER_SET_SRC_INV(*source, is_neg);
    if (changed) {
        if(mp->cur_template == MIXERTEMPLATE_COMPLEX) {
            guiObject_t *trim = _get_obj(COMPLEX_TRIM, 0);
            if(trim) {
                if (MIXER_SourceHasTrim(MIXER_SRC(mp->mixer[0].src)))
                    GUI_SetHidden(trim, 0);
                else
                    GUI_SetHidden(trim, 1);
            }
        }
        sync_mixers();
        MIXPAGE_RedrawGraphs();
    }
    GUI_TextSelectEnablePress((guiTextSelect_t *)obj, MIXER_SRC(*source));
    return INPUT_SourceName(mp->tmpstr, *source);
}
Exemplo n.º 2
0
const char *set_drsource_cb(guiObject_t *obj, int dir, void *data)
{
    (void) obj;
    u8 *source = (u8 *)data;
    u8 is_neg = MIXER_SRC_IS_INV(*source);
    u8 changed;
    u8 oldsrc = *source;
    *source = GUI_TextSelectHelper(MIXER_SRC(*source), 0, NUM_SOURCES, dir, 1, 1, &changed);
    MIXER_SET_SRC_INV(*source, is_neg);
    if (changed) {
        sync_mixers();
        if ((!! MIXER_SRC(oldsrc)) ^ (!! MIXER_SRC(*source))) {
            // bug fix (issues #191) : only invoke _update_rate_widgets() for expo template
            if (mp->cur_template == MIXERTEMPLATE_EXPO_DR) {
                if(data == &mp->mixer[1].sw)
                    _update_rate_widgets(0);
                else if(data == &mp->mixer[2].sw)
                    _update_rate_widgets(1);
            }
        } else {    
            MIXPAGE_RedrawGraphs();
        }
    }
    GUI_TextSelectEnablePress((guiTextSelect_t *)obj, MIXER_SRC(*source));
    return INPUT_SourceName(mp->tmpstr, *source);
}
Exemplo n.º 3
0
s16 eval_mixer_cb(s16 xval, void * data)
{
    struct Mixer *mix = data ? (struct Mixer *)data : mp->cur_mixer;
    if (MIXER_SRC_IS_INV(mix->src))
        xval = -xval;
    s16 yval = CURVE_Evaluate(xval, &mix->curve);
    yval = yval * mix->scalar / 100 + PCT_TO_RANGE(mix->offset);

    /* Min/Max is a servo limit, shouldn't be shown here
    if(mix->dest < NUM_OUT_CHANNELS) {
        if (yval > PCT_TO_RANGE(mp->limit.max))
            yval = PCT_TO_RANGE(mp->limit.max);
        else if (yval < PCT_TO_RANGE(mp->limit.min))
            yval = PCT_TO_RANGE(mp->limit.min);
    }
    */

    if (yval > CHAN_MAX_VALUE * 5 / 4)
        yval = CHAN_MAX_VALUE * 5 / 4;
    else if (yval <CHAN_MIN_VALUE * 5 / 4)
        yval = CHAN_MIN_VALUE * 5 / 4;
    //Don't showchannel-reverse on the graph (but do show input reverse)
    //if (mp->limit.flags & CH_REVERSE)
    //    yval = -yval;
    return yval;
}
Exemplo n.º 4
0
void sourceselect_cb(guiObject_t *obj, void *data)
{
    u8 *source = (u8 *)data;
    if (MIXER_SRC(*source)) {
        MIXER_SET_SRC_INV(*source, ! MIXER_SRC_IS_INV(*source));
        GUI_Redraw(obj);
        MIXPAGE_RedrawGraphs();
    }
}
Exemplo n.º 5
0
void toggle_source_cb(guiObject_t *obj, void *data)
{
    u8 idx = (long)data;
    struct Timer *timer = &Model.timer[idx];
    if(MIXER_SRC(timer->src)) {
        MIXER_SET_SRC_INV(timer->src, ! MIXER_SRC_IS_INV(timer->src));
        TIMER_Reset(idx);
        GUI_Redraw(obj);
    }
}
Exemplo n.º 6
0
unsigned switch_is_on(unsigned sw, volatile s32 *raw)
{
    unsigned is_neg = MIXER_SRC_IS_INV(sw);
    sw = MIXER_SRC(sw);
    if(sw == 0) {
        // No switch selected is the same as an on switch
        return 1;
    }
    s32 value = raw[sw];
    if (is_neg)
        value = - value;
    return (value > 0);
}
Exemplo n.º 7
0
s16 STDMIX_EvalMixerCb(s16 xval, struct Mixer *mix, s16 max_value, s16 min_value)
{
    if (MIXER_SRC_IS_INV(mix->src))
        xval = -xval;
    s16 yval = CURVE_Evaluate(xval, &mix->curve);
    yval = yval * mix->scalar / 100 + PCT_TO_RANGE(mix->offset);

    if (yval > max_value)
        yval = max_value;
    else if (yval <min_value)
        yval = min_value;
    return yval;
}
Exemplo n.º 8
0
void PAGE_EditCurvesInit(int page)
{
    (void)page;
    struct Curve *curve = edit->curveptr;
    u8 type = CURVE_TYPE(curve);
    PAGE_SetActionCB(action_cb);
    edit->pointnum = 0;
    edit->reverse = MIXER_SRC_IS_INV(pagemem.u.mixer_page.cur_mixer->src);
    if ((type == CURVE_EXPO || type == CURVE_DEADBAND)
        && curve->points[0] == curve->points[1])
    {
        edit->pointnum = -1;
    }
    edit->curve = *curve;

    GUI_CreateTextSelectPlate(&gui->name, NAME_X, 0, NAME_W, HEADER_HEIGHT, &TEXTSEL_FONT, NULL, set_curvename_cb, NULL);
    GUI_CreateButtonPlateText(&gui->save, SAVE_X, 0, SAVE_W, HEADER_WIDGET_HEIGHT, &BUTTON_FONT , NULL, okcancel_cb, (void *)_tr("Save"));
    // Draw a line
    if (UNDERLINE)
        GUI_CreateRect(&gui->rect, 0, HEADER_WIDGET_HEIGHT, LCD_WIDTH, 1, &DEFAULT_FONT);

    u8 space = LINE_SPACE;
    u8 y = space;

    if (type >= CURVE_3POINT) {
        GUI_CreateLabelBox(&gui->smoothlbl, LABEL_X, y, LABEL1_W, LINE_HEIGHT, &LABEL_FONT, NULL, NULL, _tr("Smooth"));
        GUI_CreateTextSelectPlate(&gui->smooth, TEXTSEL1_X, y, TEXTSEL1_W, LINE_HEIGHT, &TEXTSEL_FONT, NULL, set_smooth_cb, NULL);
        y += space;
        GUI_CreateLabelBox(&gui->pointlbl, LABEL_X, y , LABEL2_W, LINE_HEIGHT, &LABEL_FONT, NULL, NULL, _tr("Point"));
        GUI_CreateTextSelectPlate(&gui->point, TEXTSEL2_X, y, TEXTSEL2_W, LINE_HEIGHT, &TEXTSEL_FONT, NULL, set_pointnum_cb, NULL);
    } else if(type == CURVE_DEADBAND || type == CURVE_EXPO) {
        GUI_CreateLabelBox(&gui->pointlbl, LABEL_X, y , LABEL_W, LINE_HEIGHT, &LABEL_FONT, NULL, NULL, _tr("Pos/Neg"));
        y += space;
        GUI_CreateTextSelectPlate(&gui->point, LABEL_X, y, LABEL_W, LINE_HEIGHT, &TEXTSEL_FONT, NULL, set_expopoint_cb, NULL);
    }

    y += space;
    GUI_CreateLabelBox(&gui->valuelbl, LABEL_X, y , LABEL_W, LINE_HEIGHT, &LABEL_FONT, NULL, NULL, _tr("Value"));
    y += VALUE_Y_OFFSET;
    GUI_CreateTextSelectPlate(&gui->value, VALUE_X, y, LABEL_W, LINE_HEIGHT, &TEXTSEL_FONT, NULL, set_value_cb, NULL);

    GUI_CreateXYGraph(&gui->graph, GRAPH_X, GRAPH_Y, GRAPH_W, GRAPH_H,
                              CHAN_MIN_VALUE, CHAN_MIN_VALUE,
                              CHAN_MAX_VALUE, CHAN_MAX_VALUE,
                              0, 0, //CHAN_MAX_VALUE / 4, CHAN_MAX_VALUE / 4,
                              show_curve_cb, NULL, touch_cb, &edit->curve);
    GUI_SetSelected((guiObject_t *)&gui->point);
}
Exemplo n.º 9
0
const char *_set_src_cb(guiTextSelect_t *obj, u8 *src, int dir, int idx, int source)
{
    u8 changed;
    if (Model.mixer_mode == MIXER_STANDARD && Model.type == MODELTYPE_HELI)  { //Improvement: only to intelligent switch setting for heli type in standard mode
        int is_neg = MIXER_SRC_IS_INV(*src);
        int step = mapped_std_channels.throttle + NUM_INPUTS +1;
        int newsrc = GUI_TextSelectHelper(MIXER_SRC(*src), 0, step, dir, step, step, &changed);
        MIXER_SET_SRC_INV(newsrc, is_neg);
        *src = newsrc;
    } else {
        if (source <= INP_NONE)
            *src = INPUT_SelectSource(*src, dir, &changed);
        else
            *src = INPUT_SelectInput(*src, source, &changed);
    }
    if (changed) {
        TIMER_Reset(idx);
    }
    GUI_TextSelectEnablePress(obj, MIXER_SRC(*src));
    return INPUT_SourceName(tempstring, *src);
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
void TIMER_Update()
{
    unsigned i;
    unsigned chan_val = 0;
    u32 t = CLOCK_getms();
    if (PROTOCOL_WaitingForSafe())
        return;
    if( Transmitter.power_alarm > 0 )
        TIMER_Power();
    for (i = 0; i < NUM_TIMERS; i++) {
        if (Model.timer[i].src) {
            s16 val;
            if (MIXER_SRC(Model.timer[i].src) <= NUM_INPUTS) {
                volatile s16 *raw = MIXER_GetInputs();
                val = raw[MIXER_SRC(Model.timer[i].src)];
            } else {
                val = MIXER_GetChannel(Model.timer[i].src - NUM_INPUTS - 1, APPLY_SAFETY);
            }
            if (MIXER_SRC_IS_INV(Model.timer[i].src))
                val = -val;
            if (Model.timer[i].type == TIMER_STOPWATCH_PROP
                || Model.timer[i].type == TIMER_COUNTDOWN_PROP)
            {
               chan_val = RANGE_TO_PCT(abs(val));
               if (chan_val > 100)
                   chan_val = 100;
            } else {
                unsigned new_state = (val - CHAN_MIN_VALUE > (CHAN_MAX_VALUE - CHAN_MIN_VALUE) / 20) ? 1 : 0;
                if (new_state != timer_state[i]) {
                    if (new_state)
                        last_time[i] = t;
                    timer_state[i] = new_state;
                }
            }
        }
        if (timer_state[i]) {
            s32 delta = t - last_time[i];
            if (Model.timer[i].type == TIMER_STOPWATCH_PROP || Model.timer[i].type == TIMER_COUNTDOWN_PROP) {
                delta = delta * chan_val / 100;
            }
            if (Model.timer[i].type == TIMER_PERMANENT) {
                timer_val[i] += delta;
                if( timer_val[i] >= 359999900) // Reset when 99h59mn59sec
                    timer_val[i] = 0 ;
                Model.timer[i].val = timer_val[i];
            } else if (Model.timer[i].type == TIMER_STOPWATCH || Model.timer[i].type == TIMER_STOPWATCH_PROP) {
                timer_val[i] += delta;
            } else {
                s32 warn_time;
                // start to beep  for each prealert_interval at the last prealert_time(seconds)
                if (Transmitter.countdown_timer_settings.prealert_time != 0 &&
                    Transmitter.countdown_timer_settings.prealert_interval != 0 &&
                    timer_val[i] > Transmitter.countdown_timer_settings.prealert_interval &&
                    timer_val[i] < (s32)Transmitter.countdown_timer_settings.prealert_time + 1000) { // give extra 1seconds
                    warn_time = ((timer_val[i] / Transmitter.countdown_timer_settings.prealert_interval)
                            * Transmitter.countdown_timer_settings.prealert_interval);
                    if (timer_val[i] > warn_time && (timer_val[i] - delta) <= warn_time) {
                        MUSIC_Play(MUSIC_TIMER_WARNING);
                    }
                }
                // Beep once for each timeup_interval past 0
                if (timer_val[i] < 0 && Transmitter.countdown_timer_settings.timeup_interval != 0) {
                    warn_time = ((timer_val[i] - Transmitter.countdown_timer_settings.timeup_interval) / Transmitter.countdown_timer_settings.timeup_interval)
                            * Transmitter.countdown_timer_settings.timeup_interval;
                    if (timer_val[i] > warn_time && (timer_val[i] - delta) <= warn_time) {
                        MUSIC_Play(MUSIC_ALARM1 + i);
                    }
                }
                if (timer_val[i] >= 0 && timer_val[i] < delta) {
                    MUSIC_Play(MUSIC_ALARM1 + i);
                }
                timer_val[i] -= delta;
            }
            last_time[i] = t;
        } 
        if (Model.timer[i].resetsrc) {
            s16 val;
            if (MIXER_SRC(Model.timer[i].resetsrc) <= NUM_INPUTS) {
                volatile s16 *raw = MIXER_GetInputs();
                val = raw[MIXER_SRC(Model.timer[i].resetsrc)];
            } else {
                val = MIXER_GetChannel(Model.timer[i].resetsrc - NUM_INPUTS - 1, APPLY_SAFETY);
            }
            if (MIXER_SRC_IS_INV(Model.timer[i].resetsrc))
                val = -val;
            if (val - CHAN_MIN_VALUE > (CHAN_MAX_VALUE - CHAN_MIN_VALUE) / 20) {
                TIMER_Reset(i);
            }
        }
    }
}