Beispiel #1
0
static const char *safety_string_cb(guiObject_t *obj, void *data)
{
    (void)data;
    int i;
    u32 crc = Crc(tempstring, strlen(tempstring));
    if (obj && crc == dialogcrc)
        return tempstring;
    int count = 0;
    const s8 safeval[4] = {0, -100, 0, 100};
    volatile s16 *raw = MIXER_GetInputs();
    u64 unsafe = PROTOCOL_CheckSafe();
    tempstring[0] = 0;
    for(i = 0; i < NUM_SOURCES + 1; i++) {
        if (! (unsafe & (1LL << i)))
            continue;
        int ch = (i == 0) ? PROTOCOL_MapChannel(INP_THROTTLE, NUM_INPUTS + 2) : i-1;
      
        s16 val = RANGE_TO_PCT((ch < NUM_INPUTS)
                      ? raw[ch+1]
                      : MIXER_GetChannel(ch - (NUM_INPUTS), APPLY_SAFETY));
        INPUT_SourceName(tempstring + strlen(tempstring), ch + 1);
        int len = strlen(tempstring);
        snprintf(tempstring + len, sizeof(tempstring) - len, _tr(" is %d%%, safe value = %d%%\n"),
                val, safeval[Model.safety[i]]);
        if (++count >= 5)
            break;
    }
    return tempstring;
}
Beispiel #2
0
u64 PROTOCOL_CheckSafe()
{
    int i;
    volatile s32 *raw = MIXER_GetInputs();
    u64 unsafe = 0;
    for(i = 0; i < NUM_SOURCES + 1; i++) {
        if (! Model.safety[i])
            continue;
        int ch;
        if (i == 0) {
            //Auto mode (choose 'THR' channel (or CH3)
            ch = PROTOCOL_MapChannel(INP_THROTTLE, NUM_INPUTS + 2);
        } else {
            ch = i-1;
        }
        s32 val = RANGE_TO_PCT((ch < NUM_INPUTS)
                      ? raw[ch+1]
                      : MIXER_GetChannel(ch - (NUM_INPUTS), APPLY_SAFETY));
        if (Model.safety[i] == SAFE_MIN && val > -99)
            unsafe |= 1ULL << i;
        else if (Model.safety[i] == SAFE_ZERO && (val < -1 || val > 1))
            unsafe |= 1ULL << i;
        else if (Model.safety[i] == SAFE_MAX && val < 99)
            unsafe |= 1ULL << i;
    }
    return unsafe;
}
Beispiel #3
0
s32 get_boxval(u8 idx)
{
#if HAS_RTC
    if (idx <= NUM_RTC) {
        u32 time = RTC_GetValue();
        return idx == 1 ? RTC_GetTimeValue(time) : RTC_GetDateValue(time);
    }
#endif
    if (idx - NUM_RTC <= NUM_TIMERS)
        return TIMER_GetValue(idx - NUM_RTC - 1);
    if(idx - NUM_RTC - NUM_TIMERS <= NUM_TELEM)
        return TELEMETRY_GetValue(idx - NUM_RTC - NUM_TIMERS);
    return RANGE_TO_PCT(MIXER_GetChannel(idx - (NUM_RTC + NUM_TIMERS + NUM_TELEM + 1), APPLY_SAFETY | APPLY_SCALAR));
}
Beispiel #4
0
static void build_data_pkt()
{
    int i;
    for (i = 0; i < USBHID_MAX_CHANNELS; i++) {
        if (i >= num_channels) {
            packet[i] = 0;
            continue;
        }
        s32 value = RANGE_TO_PCT(Channels[i]);
        if (value > 127)
            value = 127;
        else if (value < -127)
            value = -127;
        packet[i] = value;
    }
}
Beispiel #5
0
const char *show_box_cb(guiObject_t *obj, const void *data)
{
    (void)obj;
    u8 idx = (long)data;
    #if HAS_RTC
        if (idx <= NUM_RTC) {
            u32 time = RTC_GetValue();
            idx == 1 ? RTC_GetTimeFormatted(tempstring, time) : RTC_GetDateFormatted(tempstring, time);
            return tempstring;
        }
    #endif
    if (idx - NUM_RTC <= NUM_TIMERS) {
        TIMER_SetString(tempstring, TIMER_GetValue(idx - NUM_RTC - 1));
    } else if(idx - NUM_RTC - NUM_TIMERS <= NUM_TELEM) {
        TELEMETRY_GetValueStr(tempstring, idx - NUM_RTC - NUM_TIMERS);
    } else {
        sprintf(tempstring, "%3d%%", RANGE_TO_PCT(MIXER_GetChannel(idx - (NUM_RTC + NUM_TIMERS + NUM_TELEM + 1), APPLY_SAFETY | APPLY_SCALAR)));
    }
    return tempstring;
}
Beispiel #6
0
void PAGE_ChantestEvent()
{
    int i;
    if(cp->type == MONITOR_BUTTONTEST) {
        _handle_button_test();
        return;
    }
    volatile s16 *raw = MIXER_GetInputs();
    for(i = 0; i < cp->num_bars; i++) {
        int j = _get_input_idx(i);
        int v = RANGE_TO_PCT(cp->type ? raw[j+1] : Channels[j]);
        if (v != cp->pctvalue[i]) {
            guiObject_t *obj = _get_obj(i, ITEM_GRAPH);
            if (obj) {
                GUI_Redraw(obj);
                GUI_Redraw(_get_obj(i, ITEM_VALUE));
            }
            cp->pctvalue[i] = v;
        }
    }
}
void PAGE_ChantestEvent()
{
    if(cp->type == MONITOR_BUTTONTEST) {
        _handle_button_test();
        return;
    }
    volatile s32 *raw = MIXER_GetInputs();
    for(int i = 0; i < cp->num_bars; i++) {
        int ch = get_channel_idx(cur_row * NUM_BARS_PER_ROW + i);
        int v = RANGE_TO_PCT((ch >= NUM_INPUTS && ch < NUM_INPUTS + NUM_OUT_CHANNELS)
                             ? Channels[ch - NUM_INPUTS]
                             : raw[ch + 1]);
        if (v != cp->pctvalue[i]) {
            guiObject_t *obj = _get_obj(i, ITEM_VALUE);
            if (obj) {
                GUI_Redraw(obj);
                GUI_Redraw(_get_obj(i, ITEM_GRAPH));
            }
            cp->pctvalue[i] = v;
        }
    }
}
Beispiel #8
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;
}
Beispiel #9
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);
            }
        }
    }
}