/// <summary>
        /// Costruttore
        /// </summary>
        /// <param name="ch">Nome del canale analogico</param>
        /// <param name="scale">Valore di scalatura del valore letto dal canale analogico</param>
        /// <param name="offset">Offset aggiunto sul valore letto dal canale analogico</param>
        /// <param name="movingAverageSize">Dimensione del buffer per calcolo media</param>
        public UniversalIO(UIO_ADC ch, double scale, double offset, int movingAverageSize)
        {
            UIODigitalOutput cha;

            switch (ch)
            {
            case UIO_ADC.UIO_ADC_3:
                SelPort = UIOSelector.OUT_SEL_3;
                cha     = UIODigitalOutput.UIO_OUT_3;
                break;

            case UIO_ADC.UIO_ADC_4:
                SelPort = UIOSelector.OUT_SEL_4;
                cha     = UIODigitalOutput.UIO_OUT_4;
                break;

            case UIO_ADC.UIO_ADC_6:
                SelPort = UIOSelector.OUT_SEL_6;
                cha     = UIODigitalOutput.UIO_OUT_6;
                break;

            case UIO_ADC.UIO_ADC_7:
                SelPort = UIOSelector.OUT_SEL_7;
                cha     = UIODigitalOutput.UIO_OUT_7;
                break;

            case UIO_ADC.UIO_ADC_8:
                SelPort = UIOSelector.OUT_SEL_8;
                cha     = UIODigitalOutput.UIO_OUT_8;
                break;

            default:
                throw new ArgumentException("ADC non valido", "ch");
            }
            // spengo mosfet per non influenzare lettura ADC
            DigitalOut = new DigitalOutput((Output)cha);
            DigitalOut.Write(false);

            Initialize(UIOMode.UIOModeAnalogInput, (int)SelPort, (int)ch, movingAverageSize, true, scale, offset);
        }
        private void Initialize(UIOMode mode, int select, int hwres, int intParam, bool isDigital, double scale, double offset)
        {
            _uioMode = mode;
            SelPort = (UIOSelector)select;

            switch (mode)
            {
                case UIOMode.UIOModeDigitalInput:
                    break;
                case UIOMode.UIOModeDigitalOutput:
                    DigitalOut = new DigitalOutput((Output)hwres);
                    break;
                case UIOMode.UIOModeAnalogInput:
                    _avg = new MovingAverageCalculator(intParam);
                    AnalogIn = new AnalogIn((ADC)hwres, scale, offset, intParam) {Scale = scale, Offset = offset};
                    break;
                case UIOMode.UIOModeSoftPwm:
                    if (intParam < 1 || intParam > 1000)
                        throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1000 Hz", "freq");
                    //creo ed avvio il PWM software
                    _softPwm = new SoftPWM(intParam, (Cpu.Pin)hwres);
                    SoftPWM.Start();
                    break;
                case UIOMode.UIOModeRealPwm:
                    if (intParam < 1 || intParam > 1000000)
                        throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1 MHz", "freq");
                    //creo ed avvio il PWM hardware
                    _realPwm = new PWM((Cpu.PWMChannel)hwres, intParam, 0, false);
                    _realPwm.Start();
                    break;
                case UIOMode.UIOModeSoftDac:
                    if (intParam < 1 || intParam > 1000)
                        throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1000 Hz", "freq");
                    //creo ed avvio il PWM software
                    _softPwm = new SoftPWM(intParam, (Cpu.Pin)hwres);
                    SoftPWM.Start();
                    break;
                case UIOMode.UIOModeRealDac:
                    if (intParam < 1 || intParam > 1000000)
                        throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1 MHz", "freq");
                    //creo ed avvio il PWM hardware
                    _realPwm = new PWM((Cpu.PWMChannel)hwres, intParam, 0, false);
                    _realPwm.Start();
                    break;
                default:
                    break;
            }

            //seleziono sul modulo il tipo di uscita DAC/PWM
            _pwmSel = new DigitalOutput((Output)SelPort);
            _pwmSel.Write(isDigital);

        }
        /// <summary>
        /// Costruttore
        /// </summary>
        /// <param name="ch">Nome del canale analogico</param>
        /// <param name="scale">Valore di scalatura del valore letto dal canale analogico</param>
        /// <param name="offset">Offset aggiunto sul valore letto dal canale analogico</param>
        /// <param name="movingAverageSize">Dimensione del buffer per calcolo media</param>
        public UniversalIO(UIO_ADC ch, double scale, double offset, int movingAverageSize)
        {
            UIODigitalOutput cha;

            switch (ch)
            {
                case UIO_ADC.UIO_ADC_3:
                    SelPort = UIOSelector.OUT_SEL_3;
                    cha = UIODigitalOutput.UIO_OUT_3;
                    break;
                case UIO_ADC.UIO_ADC_4:
                    SelPort = UIOSelector.OUT_SEL_4;
                    cha = UIODigitalOutput.UIO_OUT_4;
                    break;
                case UIO_ADC.UIO_ADC_6:
                    SelPort = UIOSelector.OUT_SEL_6;
                    cha = UIODigitalOutput.UIO_OUT_6;
                    break;
                case UIO_ADC.UIO_ADC_7:
                    SelPort = UIOSelector.OUT_SEL_7;
                    cha = UIODigitalOutput.UIO_OUT_7;
                    break;
                case UIO_ADC.UIO_ADC_8:
                    SelPort = UIOSelector.OUT_SEL_8;
                    cha = UIODigitalOutput.UIO_OUT_8;
                    break;
                default:
                    throw new ArgumentException("ADC non valido", "ch");
            }
            // spengo mosfet per non influenzare lettura ADC
            DigitalOut = new DigitalOutput((Output)cha);
            DigitalOut.Write(false);

            Initialize(UIOMode.UIOModeAnalogInput, (int)SelPort, (int)ch, movingAverageSize, true, scale, offset);
                  
        }
        private void Initialize(UIOMode mode, int select, int hwres, int intParam, bool isDigital, double scale, double offset)
        {
            _uioMode = mode;
            SelPort  = (UIOSelector)select;

            switch (mode)
            {
            case UIOMode.UIOModeDigitalInput:
                break;

            case UIOMode.UIOModeDigitalOutput:
                DigitalOut = new DigitalOutput((Output)hwres);
                break;

            case UIOMode.UIOModeAnalogInput:
                _avg     = new MovingAverageCalculator(intParam);
                AnalogIn = new AnalogIn((ADC)hwres, scale, offset, intParam)
                {
                    Scale = scale, Offset = offset
                };
                break;

            case UIOMode.UIOModeSoftPwm:
                if (intParam < 1 || intParam > 1000)
                {
                    throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1000 Hz", "freq");
                }
                //creo ed avvio il PWM software
                _softPwm = new SoftPWM(intParam, (Cpu.Pin)hwres);
                SoftPWM.Start();
                break;

            case UIOMode.UIOModeRealPwm:
                if (intParam < 1 || intParam > 1000000)
                {
                    throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1 MHz", "freq");
                }
                //creo ed avvio il PWM hardware
                _realPwm = new PWM((Cpu.PWMChannel)hwres, intParam, 0, false);
                _realPwm.Start();
                break;

            case UIOMode.UIOModeSoftDac:
                if (intParam < 1 || intParam > 1000)
                {
                    throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1000 Hz", "freq");
                }
                //creo ed avvio il PWM software
                _softPwm = new SoftPWM(intParam, (Cpu.Pin)hwres);
                SoftPWM.Start();
                break;

            case UIOMode.UIOModeRealDac:
                if (intParam < 1 || intParam > 1000000)
                {
                    throw new ArgumentOutOfRangeException("Il valore deve essere compreso nel range 1...1 MHz", "freq");
                }
                //creo ed avvio il PWM hardware
                _realPwm = new PWM((Cpu.PWMChannel)hwres, intParam, 0, false);
                _realPwm.Start();
                break;

            default:
                break;
            }

            //seleziono sul modulo il tipo di uscita DAC/PWM
            _pwmSel = new DigitalOutput((Output)SelPort);
            _pwmSel.Write(isDigital);
        }