Subversion Repositories group.electronics

Rev

Rev 189 | Blame | Compare with Previous | Last modification | View Log | RSS feed

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace nitdcscore {

    public class jsaxis {
        public UInt16 prev { get; set; }        // The previous ADC value
        public UInt16 value { get; set; }       // The current ADC value
        public UInt16 thres { get; set; }       // Threshold to report a new position
        public UInt16 max { get; set; }              // The maximum value we've seen
        public UInt16 mapsize { get; set; }     // The mapping maximum

        public jsaxis() {

        }

        public bool getPosition(ref UInt16 position) {
            if (this.value > this.max)
                this.max = this.value;

            UInt16 lowerval = 0;
            if (this.prev >= this.thres)
                lowerval = (UInt16)(this.prev - this.thres);

            ushort upperval = this.max;
            if (this.prev <= upperval - this.thres)
                upperval = (ushort)(this.prev + this.thres);

            if ((this.value < lowerval) || (this.value > upperval)) {
                // Cover our min/max ranges within threshold
                if (this.value < this.thres)
                    this.value = 0;
                if (this.value > this.max - this.thres)
                    this.value = this.max;

                // Only update the prev value once we've moved out of the
                //  threshold and triggered an update
                this.prev = this.value;

                position = Globals.map_uint16(this.value, 0, this.max, 0, this.mapsize);

                return true;
            }

            return false;
        }
    }

    public class jsdata {
        public bool changed { get; set; }
        public UInt64 buttons { get; set; }
        public UInt64 prev { get; set; }

        public jsaxis[] axis = new jsaxis[6];

        public jsdata() {
            changed = false;
            prev = buttons = 0;

            for (int i = 0; i < 6; i++) {
                axis[i] = new jsaxis();
                axis[i].thres = Globals.ADC_THRESHOLD;
                axis[i].max = Globals.ADC_DEFMAX;
                axis[i].prev = axis[i].value = 0;
                axis[i].mapsize = 0xffff;
            }
        }
    }

    public class Led {
        public int bank { get; set; }
        public int pin { get; set; }
        public UInt16 address { get; set; }
        public UInt16 mask { get; set; }
        public int shift { get; set; }
        public uint value { get; set; }
        private UInt16 prevdata;

        public Led(int bank, int pin, UInt16 address, UInt16 mask, int shift) {
            this.pin = pin;
            this.address = address;
            this.mask = mask;
            this.shift = shift;
            this.value = 0;

            UInt16 data;
            if (!Globals.BiosOutput.TryGetValue(this.address, out data)) {
                Globals.BiosOutput.Add(this.address, 0x0000);
            }

        }

        public bool Tick(ref byte shadow) {
           
            UInt16 data;
            byte tmpshadow = shadow;
            if (Globals.BiosOutput.TryGetValue(this.address, out data)) {
                // Only continue if the data parm has changed
                if (data == this.prevdata)
                    return false;
                this.prevdata = data;

                this.value = (UInt16)((data & mask) >> shift);

                if (this.value == 1)
                    Globals.setBit(ref shadow, this.pin);
                else
                    Globals.clearBit(ref shadow, this.pin);
            }

            // Only update the led if the led value has changed
            if (tmpshadow == shadow)
                return false;

            // Return true to signal the panel to update the led
            return true;
        }

        public bool Tick(ref UInt16 shadow) {

            UInt16 data;
            UInt16 tmpshadow = shadow;
            if (Globals.BiosOutput.TryGetValue(this.address, out data)) {
                // Only continue if the data parm has changed
                if (data == this.prevdata)
                    return false;
                this.prevdata = data;

                this.value = (UInt16)((data & mask) >> shift);

                if (this.value == 1) {
                    Globals.setBit(ref shadow, this.pin);
                } else {
                    Globals.clearBit(ref shadow, this.pin);
                }
            }

            // Only update the led if the led value has changed
            if (tmpshadow == shadow)
                return false;

            // Return true to signal the panel to update the led
            return true;
        }

    }


    public abstract class Control {
        public UInt64 value { get; set; }

        public Control(Command command) {
            commands.Add(command);
        }

        public List<Command> commands = new List<Command>();
        public jsdata data { get; set; }
        public Boolean updated { get; set; }

        public abstract void Tick();
    }

    public class Switch2Pos : Control {
        public int pin { get; set; }
        
        public Boolean invert { get; set; }

        public Switch2Pos(Command command, int pin, Boolean invert = false) : base(command) {
            this.invert = invert;
            this.pin = pin;
        }

        public override void Tick() {
            UInt64 chg = (UInt64)(data.prev >> pin) & 0x01;
            UInt64 norm = (UInt64)(data.buttons >> pin) & 0x01;
            this.value = 0;

            if ((UInt64)(norm) == 1) {
                value = (UInt64)(invert ? 0 : 1);
            } else {
                value = (UInt64)(invert ? 1 : 0);
            }

            if (this.commands != null && norm != chg) {
                foreach (Command cmd in this.commands) {
                    cmd.data = this.data;
                    if (cmd.Send(this.value) == 0)
                        Console.Write(cmd.ToString());
                }
            }
        }
    }

    public class Switch3Pos : Control {
        public int pin0 { get; set; }
        public int pin1 { get; set; }

        public Boolean invert { get; set; }

        public Switch3Pos(Command command, int pin0, int pin1, Boolean invert = false) : base(command) {
            this.pin0 = pin0;
            this.pin1 = pin1;
            this.invert = invert;
            
        }

        public override void Tick() {
            UInt64 chg0 = (UInt64)(data.prev >> pin0) & 0x01;
            UInt64 chg1 = (UInt64)(data.prev >> pin1) & 0x01;
            UInt64 nrm0 = (UInt64)(data.buttons >> pin0) & 0x01;
            UInt64 nrm1 = (UInt64)(data.buttons >> pin1) & 0x01;
            this.value = 1;

            if ((UInt64)nrm0 == 1)
                this.value = (UInt64)(invert ? 2 : 0);
            else if ((uint)nrm1 == 1)
                this.value = (UInt64)(invert ? 0 : 2);

            if (this.commands != null &&  ((nrm0 != chg0) || (nrm1 != chg1))) {
                foreach (Command cmd in this.commands) {
                    if (cmd == null) {
                        Console.WriteLine("Null data");
                    } else {
                        cmd.data = this.data;
                        if (cmd.Send(this.value) == 0)
                            Console.Write(cmd.ToString());
                    }
                }
            }
        }
    }

    public class Potentiometer : Control {
        public int channel { get; set; }

        public Boolean invert { get; set; }

        public Potentiometer(Command command, int channel) : base(command) {
            this.channel = channel;
        }

        public override void Tick() {
            UInt16 tmpval = 0;
            bool changed = data.axis[channel].getPosition(ref tmpval);

            if (changed) {
                this.value = tmpval;
                foreach (Command cmd in this.commands) {
                    cmd.data = this.data;
                    if (cmd.Send(this.value) == 0)
                        Console.Write(cmd.ToString());
                }
            }
        }
    }

    public class Selector : Control {
        int[] pins;


        public Selector(Command command, int[] pins) : base(command) {
            this.pins = pins;
            this.value = 0;
        }

        public override void Tick() {
            // This is a rather complicated way  to check what the previous select
            //  was, and was the current selection is. Not really needed, but hoping it 
            //  might come in handy for something else down the line.
            UInt64 chg = 0;
            UInt64 norm = 0;
            UInt64 mask = 0;
            for (int i = 0; i < pins.Length; i++) // Create a mask of how many selection points there are
                mask |= (UInt64)1 << i;

            for (int i = 0; i < pins.Length; i++) {
                chg |= (UInt64)(data.prev >> (pins[i] - i)); // Narrow down to the previsouly selected bit
                norm |= (UInt64)(data.buttons >> (pins[i] - i)); // Narrow down to the currently selected bit

                if ((UInt64)((data.buttons >> pins[i]) & 0x01) == 1) { // Decode the value we need to use
                    value = (UInt64)i;
                }
            }
                           
            norm &= mask; // Remove any bits from above
            chg &= mask;

            if (norm == 0) // Can sometimes be in the inbetween selector switch, ignore
                return;

            if (norm != chg) { // Send the update if needed
                foreach (Command cmd in this.commands) {
                    cmd.data = this.data;
                    if (cmd.Send(this.value) == 0)
                        Console.Write(cmd.ToString());
                }
            }
        }

    }
}