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

using Acroname.BrainStem2CLI;

namespace BrainStem2CLI_BulkCapture
{
    class Program
    {
        static void Main(string[] args)
        {

            //Constants
            const int BULK_CAPTURE_CHANNEL = 0;
            const int NUM_SAMPLES = 8000;
            const int SAMPLE_RATE = 200000;

            aErr err = aErr.aErrNone;
            byte bulkCaptureState = (byte)BulkCaptureState.Idle;
            USBStem stem = new USBStem();

            //Supplying a serial number of 0 will result in the device connecting
            //to the first USBCSwitch the function finds.
            err = stem.module.discoverAndConnect(m_linkType.USB, 0);

            if (err != aErr.aErrNone)
            {
                Console.WriteLine("Error connecting to device: {0}", err);
                Console.WriteLine("Press enter to exit");
                Console.ReadLine();
                System.Environment.Exit(1);
            }
            else { Console.WriteLine("Successfully connected to BrainStem module\n"); }

            Console.WriteLine("Configuring Device for Bulk Capture");
            Console.WriteLine("Analog channel: {0}", BULK_CAPTURE_CHANNEL);
            Console.WriteLine("Number of Samples: {0}", NUM_SAMPLES);
            Console.WriteLine("Sample Rate: {0}\n", SAMPLE_RATE);

            err = stem.analog[BULK_CAPTURE_CHANNEL].setBulkCaptureNumberOfSamples(NUM_SAMPLES);
            err = stem.analog[BULK_CAPTURE_CHANNEL].setBulkCaptureSampleRate(SAMPLE_RATE);

            Console.WriteLine("Starting Bulk Caputre.");
            stem.analog[BULK_CAPTURE_CHANNEL].initiateBulkCapture();
            //Wait for Bulk Capture to finnish.
            //You can go do other stuff if you would like... Including other BrainStem functions.
            //but you will need to check that it is finnished before unloading the data
            int bailOut = 0;
            do
            {
                err = stem.analog[BULK_CAPTURE_CHANNEL].getBulkCaptureState(ref bulkCaptureState);
                if (bulkCaptureState == (byte)BulkCaptureState.Error)
                {
                    Console.WriteLine("There was an Error with Bulk Capture. Error: {0}", err);
                    break;
                }

                if(bailOut++ > 100)
                {
                    Console.WriteLine("Bulk Capture is taking longer than normal.  Giving Up.");
                    break;
                }
                Thread.Sleep(100);
            }
            while (bulkCaptureState != (byte)BulkCaptureState.Finished);

            //Get the size of the slot.
            UInt32 lengthToUnload = 0;
            err = stem.store[(byte)BrainStemStores.RAM].getSlotSize(0, ref lengthToUnload);
            if((lengthToUnload > 0)               && 
               (err == aErr.aErrNone))
            {
                Console.WriteLine("Unloading data from device");
                byte[] data = new byte[lengthToUnload];
                UInt32 unloadedLength = 0;
                err = stem.store[(byte)BrainStemStores.RAM].unloadSlot(0, lengthToUnload, ref data[0], ref unloadedLength);

                if(unloadedLength == lengthToUnload)
                {
                    for (int x = 0; x < unloadedLength; x += 2)
                    {
                        // Process 8bit values 2 bytes at a time for a 16bit value (Little Endian)
                        // i.e.
                        // val[0] = XXXXXXXX = LSB's
                        // val[1] = YYYYYYYY = MSB's
                        // combinedVal = YYYYYYYY XXXXXXXX for a 16 bit value
                        // Repeat until all the data has been processed
                        // Note: loop increments by 2.
                        UInt16 value = (UInt16)(data[x] + (data[x + 1] << 8));
                        Console.WriteLine("Sample: {0,4}, Voltage: {1,7:F6} VDC, Raw: {2,5}", (x / 2), ((value / 65535.0) * 3.3), value);
                    }
                }
                else
                {
                    Console.WriteLine("Unloaded length doesn't match the slot's data size");
                }
                
            
            }

            Console.WriteLine("Disconnecting from module");
            stem.module.disconnect();

            Console.WriteLine("Press enter to exit");
            Console.ReadLine();

        }
    }
}
