/*
 * detect_error_3_phase.c
 *
 *  Created on: 7 äåê. 2020 ã.
 *      Author: star
 */

#include "DSP281x_Examples.h"   // DSP281x Examples Include File
#include "DSP281x_Device.h"     // DSP281x Headerfile Include File
#include "IQmathLib.h"


#include <detect_error_3_phase.h>
#include <detect_phase_break.h>

#include "global_time.h"

static int detect_system_asymmetry(DETECT_PROTECT_3_PHASE *v);
static int detect_system_asymmetry_rms(DETECT_PROTECT_3_PHASE *v);

int detect_error_3_phase(DETECT_PROTECT_3_PHASE *v) {
    int err = 0;
    int asymmetry = 0;
    int break_channel = 0;

    v->errors.all = 0;
    v->over_limit.all = 0;
    if (v->setup.timers_inited == 0) {
        v->setup.timers_inited = 1;
        init_timer_milisec(&v->timer_low_minus_10);
        init_timer_milisec(&v->timer_low_minus_20);
        init_timer_milisec(&v->timer_high_plus_10);
        init_timer_milisec(&v->timer_high_plus_20);
    }

    if (v->setup.use.bits.phase_U != 0 &&
            v->iqVal_U > v->setup.levels.iqVal_U_max) {
        v->errors.bits.phase_U_max = 1;
        v->over_limit.bits.phase_U_max = 1;
        err = 1;
    }
    if (v->setup.use.bits.phase_V != 0 &&
            v->iqVal_V > v->setup.levels.iqVal_V_max) {
        v->errors.bits.phase_V_max = 1;
        v->over_limit.bits.phase_V_max = 1;
        err = 1;
    }
    if (v->setup.use.bits.phase_W != 0 &&
            v->iqVal_W > v->setup.levels.iqVal_W_max) {
        v->errors.bits.phase_W_max = 1;
        v->over_limit.bits.phase_W_max = 1;
        err = 1;
    }
    //-------------------------------------------------------------------------//
    if (v->setup.use.bits.module) {
        if (v->iqVal_mod > v->setup.levels.iqVal_module_max) {
            v->errors.bits.module_max = 1;
            v->over_limit.bits.module_max = 1;
            err = 1;
        }
    }
    //-------------------------------------------------------------------------//
    if (v->setup.use.bits.detect_minus_10 != 0) {
        if (v->iqVal_mod < v->setup.levels.iqNominal_minus10) {
            if (detect_pause_milisec(PAUSE_VAL_MINIS_10_S, &v->timer_low_minus_10)){
                v->errors.bits.module_10_percent_low = 1;
                err = 1;
            }
            v->over_limit.bits.module_10_percent_low = 1;
        } else {
            init_timer_milisec(&v->timer_low_minus_10);
        }
        v->new_timer_low_minus_10 = v->timer_low_minus_10;
    }

    if (v->setup.use.bits.detect_minus_20 != 0) {
        if (v->iqVal_mod < v->setup.levels.iqNominal_minus20) {
            if (detect_pause_milisec(PAUSE_VAL_MINIS_20_S, &v->timer_low_minus_20)) {
                v->errors.bits.module_20_percent_low = 1;
                err = 1;
            }
            v->over_limit.bits.module_20_percent_low = 1;
        } else {
            init_timer_milisec(&v->timer_low_minus_20);
        }
        v->new_timer_low_minus_20 = v->timer_low_minus_20;
    }

    if (v->setup.use.bits.detect_plus_10 != 0) {
        if (v->iqVal_mod > v->setup.levels.iqNominal_plus10) {
            if (detect_pause_milisec(PAUSE_VAL_PLUS_10_S, &v->timer_high_plus_10)) {
                v->errors.bits.module_10_percent_hi = 1;
                err = 1;
            }
            v->over_limit.bits.module_10_percent_hi = 1;
        } else {
            init_timer_milisec(&v->timer_high_plus_10);
        }
        v->new_timer_high_plus_10 = v->timer_high_plus_10;
    }

    if (v->setup.use.bits.detect_plus_20 != 0) {
        if (v->iqVal_mod > v->setup.levels.iqNominal_plus20) {
            if (detect_pause_milisec(PAUSE_VAL_PLUS_20_S, &v->timer_high_plus_20)) {
                v->errors.bits.module_20_percent_hi = 1;
                err = 1;
            }
            v->over_limit.bits.module_20_percent_hi = 1;
        } else {
            init_timer_milisec(&v->timer_high_plus_20);
        }
        v->new_timer_high_plus_20 = v->timer_high_plus_20;
    }
    //Ïðîâåðêà íà ñèììåòðè÷íîñòü 3-õ ôàçíîé ñèñòåìû. Ñóììà 3-õ ñîñòàâëÿþùèõ ðàâíà 0
    if (v->setup.use.bits.system_asymmetry_by_summ != 0) {
        asymmetry = detect_system_asymmetry(v);
        if (asymmetry != 0) {
            v->errors.bits.system_asymmetry = 1;
            err = 1;
        }
    }
    //Ïðîâåðêà íà ñèììåòðè÷íîñòü 3-õ ôàçíîé ñèñòåìû. Äåéñòâóþùèå çíà÷åíèÿ 3-õ ñîñòàâëÿþùèõ ðàâíû ìåæäó ñîáîé
    if (v->setup.use.bits.system_asymmetry_by_delta != 0) {
        asymmetry = detect_system_asymmetry_rms(v);
        if (asymmetry != 0) {
            v->errors.bits.system_asymmetry = 1;
            err = 1;
        }
    }
    //Ïðîâåðêà íà îáðûâ ôàçû. Çíà÷åíèå â îäíîì êàíàëå ðàâíî íóëþ, â îñòàëüíûå â ïðîòèâîôàçå è ðàâíû ïî ìîäóëþ
    if (v->setup.use.bits.break_phase != 0 && v->break_phase != 0) {
        v->break_phase->iqIu = v->iqVal_U;
        v->break_phase->iqIv = v->iqVal_V;
        v->break_phase->iqIw = v->iqVal_W;
        v->break_phase->iqImod = v->iqVal_mod;
        v->break_phase->teta = v->iqTeta;
        break_channel = v->break_phase->calc(v->break_phase);
        if (break_channel) {
            v->errors.bits.break_phase = 1;
            err = 1;
            switch (break_channel) {
            case 1: v->errors.bits.break_phase_U = 1; break;
            case 2: v->errors.bits.break_phase_V = 1; break;
            case 3: v->errors.bits.break_phase_W = 1; break;
            default: break;
            }
        }
    }


    return err;
}

int detect_system_asymmetry(DETECT_PROTECT_3_PHASE *v) {
    _iq sum = v->iqVal_U + v->iqVal_V + v->iqVal_W;
    return _IQabs(sum) > v->setup.levels.iqAsymmetry_delta ? 1 : 0;
}

int detect_system_asymmetry_rms(DETECT_PROTECT_3_PHASE *v) {
    _iq d1 = _IQabs(v->iqVal_U - v->iqVal_V);
    _iq d2 = _IQabs(v->iqVal_V - v->iqVal_W);
    _iq d3 = _IQabs(v->iqVal_U - v->iqVal_W);
    return d1 > v->setup.levels.iqAsymmetry_delta ||
            d2 > v->setup.levels.iqAsymmetry_delta ||
            d2 > v->setup.levels.iqAsymmetry_delta ? 1 : 0;
}