using System;
using System.Threading;
using System.IO.Ports;
using System.Text;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHI.Hardware.EMX;

// Slot 9 on FEZ Spider         J1 on SBE41CP
// Pin  1 -- VCC
// Pin  2 -- +5V
// Pin  3 -- IO46            J1.3 Space P only Mark CTD   SBE In      <-- Spider GPIO OUT
// Pin  4 -- IO6/TXD3        J1.4 Commands from Float     SBE UART RX <-- Spider UART TX        
// Pin  5 -- IO7/RXD3        J1.2 CTD Data Out            SBE UART TX --> Spider UART RX                
// Pin  6 -- IO15            J1.1 Data Request            SBE In      <-- Spider GPIO OUT
// Pin  7 -- IO24
// Pin  8 -- IO25
// Pin  9 -- IO27
// Pin 10 -- GND

namespace CPF
{
   class SBE41
    {
        private OutputPort      _dataRequest;
        private OutputPort      _space_P_OnlyMark_CTD;
        private OutputPort      _serialTX;
        private delegate void   _state(byte[] buffer);
        private AutoResetEvent  _done;
        private SerialReader    _SBE41;

        private byte[]          _lineFeed               = Encoding.UTF8.GetBytes("\r");
        private byte[]          _readPressure           = Encoding.UTF8.GetBytes("fp\r");
        private byte[]          _readPressureTurnMotor  = Encoding.UTF8.GetBytes("fpt\r");
        private byte[]          _getStatus              = Encoding.UTF8.GetBytes("ds\r");
        private byte[]          _powerDown              = Encoding.UTF8.GetBytes("qsr\r");
 
        public SBE41()
        {
            _done = new AutoResetEvent(false);
            _dataRequest = new OutputPort(Pin.IO15, false);
            _space_P_OnlyMark_CTD = new OutputPort(Pin.IO46, true);
            _SBE41 = new SerialReader("com4", 9600);
            _SBE41.Callback = null;
            PowerOff();
        }

        public void AssertDataRequest()
        {
            _dataRequest.Write(true);
        }

        public void NegateDataRequest()
        {
            _dataRequest.Write(false);
        }

        public void AssertSpace_P_OnlyMark_CTD()
        {
            _space_P_OnlyMark_CTD.Write(false);
        }

        public void NegateSpace_P_OnlyMark_CTD()
        {
            _space_P_OnlyMark_CTD.Write(true);
        }

        public void PowerOn()
        {
            AssertDataRequest();
            AssertSpace_P_OnlyMark_CTD();
            // Force entry into command mode by asserting
            // Data request for more than 400 ms
        }

        public void PowerOff()
        {
            Thread.Sleep(1000);
            NegateDataRequest();
            NegateSpace_P_OnlyMark_CTD();
        }

        private void cmdResponse_1(byte[] buffer)
        {
            string s = new string(System.Text.Encoding.UTF8.GetChars(buffer));
            Debug.Print(s);
            Thread.Sleep(1000);
            _SBE41.Callback = cmdResponse_2;
            _done.Set();
        }

        private void cmdResponse_2(byte[] buffer)
        {
            string s = new string(System.Text.Encoding.UTF8.GetChars(buffer));
            Debug.Print(s);
            if (s == "S>")
            {
                _SBE41.Stop();
                _done.Set();
            }
            else
            {
                _SBE41.Send(_lineFeed);
            }
        }     
        public void EnterCommandMode()
        {
            _SBE41.Callback = cmdResponse_1;
            _SBE41.Start();
            AssertDataRequest();
            AssertSpace_P_OnlyMark_CTD();
            _done.WaitOne();
            NegateDataRequest();
            NegateSpace_P_OnlyMark_CTD();
            Thread.Sleep(1000);
            _SBE41.Send(_lineFeed);
            _done.WaitOne();
            //GetResponse();
            //GetResponse();
            // Thread.Sleep(1000);
            //_port.ReadTimeout = 1000;
            //_port.Write(_getStatus, 0, _getStatus.Length);
            //while (true)
            //{
            //    GetResponse();
             //   Thread.Sleep(100);
            //}
        }

        private void exitCommandModeResponse(byte[] buffer)
        {
            string s = new string(System.Text.Encoding.UTF8.GetChars(buffer));
            Debug.Print(s);
            _SBE41.Stop();
            _done.Set();
        }

        public void ExitCommandMode()
        {
            _SBE41.Callback = exitCommandModeResponse;
            _SBE41.Start();
            _SBE41.Send(_powerDown);
            _done.WaitOne(); 
            Thread.Sleep(100);
        }

        public void GetPressure()
        {
            _SBE41.Dispose();
            _serialTX = new OutputPort(Pin.IO6, true);
            AssertDataRequest();
            AssertSpace_P_OnlyMark_CTD();
            Thread.Sleep(50);
            NegateDataRequest();
            Thread.Sleep(100);
            _serialTX.Write(false);
            Thread.Sleep(150);
            NegateSpace_P_OnlyMark_CTD();
            _serialTX.Write(true);
            Thread.Sleep(50);
            _serialTX.Dispose();
            //_port.Open();
            //GetResponse();
            Thread.Sleep(100);
        }
    }
}
