Implementation of 1-Wire with added Alarm Search Functionality

Dependents:   Max32630_One_Wire_Interface

Revision:
65:a28ac52ca127
Parent:
63:422be898443a
Child:
67:76776130aec9
--- a/OneWire_Masters/DS2480B/ds2480b.cpp	Tue Apr 19 21:56:03 2016 +0000
+++ b/OneWire_Masters/DS2480B/ds2480b.cpp	Wed Apr 20 21:47:42 2016 +0000
@@ -210,7 +210,11 @@
 //*********************************************************************
 void Ds2480b::rx_callback(void)
 {
-    rx_buffer.buff[rx_buffer.w_idx++] = _p_serial->getc();
+    while(_p_serial->readable())
+    {
+        rx_buffer.buff[rx_buffer.w_idx++] = _p_serial->getc();
+        rx_buffer.rx_bytes_available++;
+    }
     
     if(rx_buffer.w_idx == rx_buffer.r_idx)
     {
@@ -233,6 +237,7 @@
     
     rx_buffer.w_idx = 0;
     rx_buffer.r_idx = 0;
+    rx_buffer.rx_bytes_available = 0;
     rx_buffer.wrap_error = false;
     
     _ULevel = OneWireMaster::LEVEL_NORMAL;
@@ -706,72 +711,88 @@
 //*********************************************************************
 OneWireMaster::CmdResult Ds2480b::DS2480B_ChangeBaud(DS2480B_BPS newbaud)
 {
-   OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;
-   
-   uint8_t rt=0;
-   uint8_t readbuffer[5],sendpacket[5],sendpacket2[5];
-   uint8_t sendlen=0,sendlen2=0;
+    OneWireMaster::CmdResult result = OneWireMaster::Success;
+
+    uint8_t readbuffer[5],sendpacket[5],sendpacket2[5];
+    uint8_t sendlen=0,sendlen2=0;
+
+    //see if diffenent then current baud rate
+    if(_UBaud != newbaud) 
+    {
+        // build the command packet
+        // check for correct mode
+        if(_UMode != MODSEL_COMMAND) 
+        {
+            _UMode = MODSEL_COMMAND;
+            sendpacket[sendlen++] = MODE_COMMAND;
+        }
+        // build the command
+        sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud;
 
-   // see if diffenent then current baud rate
-   if (_UBaud == newbaud)
-   {
-      //return _UBaud;
-   }
-   else
-   {
-      // build the command packet
-      // check for correct mode
-      if (_UMode != MODSEL_COMMAND)
-      {
-         _UMode = MODSEL_COMMAND;
-         sendpacket[sendlen++] = MODE_COMMAND;
-      }
-      // build the command
-      sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud;
+        // flush the buffers
+        FlushCOM();
+
+        // send the packet
+        result = WriteCOM(sendlen,sendpacket);
+        if(result == OneWireMaster::Success)
+        {
+            // make sure buffer is flushed
+            wait_ms(5);
 
-      // flush the buffers
-      FlushCOM();
+            // change our baud rate
+            SetBaudCOM(newbaud);
+            _UBaud = newbaud;
+
+            // wait for things to settle
+            wait_ms(5);
+
+            // build a command packet to read back baud rate
+            sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
+
+            // flush the buffers
+            FlushCOM();
 
-      // send the packet
-      if (!WriteCOM(sendlen,sendpacket))
-         rt = 0;
-      else
-      {
-         // make sure buffer is flushed
-         wait_ms(5);
-
-         // change our baud rate
-         SetBaudCOM(newbaud);
-         _UBaud = newbaud;
-
-         // wait for things to settle
-         wait_ms(5);
-
-         // build a command packet to read back baud rate
-         sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
-
-         // flush the buffers
-         FlushCOM();
-
-         // send the packet
-         if(WriteCOM(sendlen2,sendpacket2))
-         {
-            // read back the 1 byte response
-            if (ReadCOM(1,readbuffer) == 1)
+            // send the packet
+            result = WriteCOM(sendlen2,sendpacket2);
+            if(result == OneWireMaster::Success) 
             {
-               // verify correct baud
-               if (((readbuffer[0] & 0x0E) == (sendpacket[sendlen-1] & 0x0E)))
-                  rt = 1;
+                // read back the 1 byte response
+                result = ReadCOM(1,readbuffer);
+                if(result == OneWireMaster::Success)
+                {
+                    // verify correct baud
+                    if((readbuffer[0] & 0x0E) == (sendpacket[sendlen-1] & 0x0E))
+                    {
+                        result = OneWireMaster::Success;
+                    }
+                    else
+                    {
+                       result = OneWireMaster::OperationFailure;
+                    }
+                }
+                else
+                {
+                    result = OneWireMaster::CommunicationReadError;
+                }
             }
-         }
-      }
-   }
-
-   // if lost communication with DS2480B then reset
-   if (rt != 1)
-      DS2480B_Detect();
-
-   return result;
+            else
+            {
+                result = OneWireMaster::CommunicationWriteError;
+            }
+        }
+        else
+        {
+            result = OneWireMaster::CommunicationWriteError;
+        }
+    }
+    
+    // if lost communication with DS2480B then reset
+    if(result != OneWireMaster::Success)
+    {
+        DS2480B_Detect();
+    }
+    
+    return result;
 }
 
 
@@ -786,10 +807,11 @@
     uint8_t idx = 0;
     
     //calculate timeout, the time needed to tx 1 byte
+    //double for 115200 due to timer object inaccuracies
     switch(_UBaud) 
     {
         case BPS_115200:
-            timeout = ((1000000/115200)*10);
+            timeout = ((1000000/115200)*20);
             break;
             
         case BPS_57600:
@@ -836,64 +858,81 @@
 OneWireMaster::CmdResult Ds2480b::ReadCOM(uint32_t inlen, uint8_t *inbuf)
 {
     OneWireMaster::CmdResult result;
+    Timer t;
     uint32_t num_bytes_read= 0;
     uint32_t timeout;
+    uint32_t micro_seconds;
     
-    //calculate timeout, 5x the time needed to recieve inlen bytes 
+    //calculate timeout, 10x the time needed to recieve inlen bytes 
+    //double for 115200 due to timer object inaccuracies
     switch(_UBaud) 
     {
         case BPS_115200:
-            timeout = ((1000000/115200)*50)*inlen;
+            timeout = ((1000000/115200)*200)*inlen;
             break;
             
         case BPS_57600:
-            timeout = ((1000000/57600)*50)*inlen;
+            timeout = ((1000000/57600)*100)*inlen;
             break;
             
         case BPS_19200:
-            timeout = ((1000000/19200)*50)*inlen;
+            timeout = ((1000000/19200)*100)*inlen;
             break;
             
         case BPS_9600:
         default:
-            timeout = ((1000000/9600)*50)*inlen;
+            timeout = ((1000000/9600)*100)*inlen;
             break;
     }
     
-    wait_us(timeout);
-    
     if(rx_buffer.wrap_error)
     {
         //reset rx buffer, error, and return failure
         rx_buffer.w_idx = 0;
         rx_buffer.r_idx = 0;
+        rx_buffer.rx_bytes_available = 0;
         rx_buffer.wrap_error = false;
         
         result = OneWireMaster::OperationFailure;
     }
     else
     {
-        if(rx_buffer.w_idx != rx_buffer.r_idx)
+        t.start();
+        t.reset();
+        do
         {
             do
             {
-                inbuf[num_bytes_read++] = rx_buffer.buff[rx_buffer.r_idx++];
+                micro_seconds = t.read_us();
             }
-            while((num_bytes_read < inlen) && (rx_buffer.w_idx != rx_buffer.r_idx));
+            while(!rx_buffer.rx_bytes_available && (micro_seconds < timeout));
             
-            if(num_bytes_read == inlen)
+            if(rx_buffer.rx_bytes_available)
             {
-                result = OneWireMaster::Success;
-            }
-            else
-            {
-                result = OneWireMaster::CommunicationReadError;
-            }
+                inbuf[num_bytes_read++] = rx_buffer.buff[rx_buffer.r_idx++];
+                rx_buffer.rx_bytes_available--;
+            } 
+        }
+        while((num_bytes_read < inlen) && (micro_seconds < timeout) && !rx_buffer.wrap_error);
+        t.stop();
+        
+        if(num_bytes_read == inlen)
+        {
+            result = OneWireMaster::Success;
+        }
+        else if(micro_seconds > timeout)
+        {
+            result = OneWireMaster::TimeoutError;
         }
         else
         {
-            //buffer empty
-            result = OneWireMaster::OperationFailure;
+            //reset rx buffer, error, and return failure
+            rx_buffer.w_idx = 0;
+            rx_buffer.r_idx = 0;
+            rx_buffer.rx_bytes_available = 0;
+            rx_buffer.wrap_error = false;
+            
+            result = OneWireMaster::CommunicationReadError;
         }
     }
     
@@ -923,6 +962,14 @@
     {
         _p_serial->getc();
     }
+    
+    /*Not sure how to flush tx buffer without sending data out on the bus.
+      from the example in AN192, the data shouldn't be sent, just aborted
+      and the buffer cleaned out, http://pdfserv.maximintegrated.com/en/an/AN192.pdf
+      Below is what was used in AN192 example code using windows drivers
+    */
+
+    //PurgeComm(ComID, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
 }
 
 
@@ -954,20 +1001,26 @@
 //*********************************************************************
 int32_t Ds2480b::bitacc(uint32_t op, uint32_t state, uint32_t loc, uint8_t *buf)
 {
-   int nbyt,nbit;
+    int nbyt,nbit;
 
-   nbyt = (loc / 8);
-   nbit = loc - (nbyt * 8);
+    nbyt = (loc / 8);
+    nbit = loc - (nbyt * 8);
 
-   if (op == WRITE_FUNCTION)
-   {
-      if (state)
-         buf[nbyt] |= (0x01 << nbit);
-      else
-         buf[nbyt] &= ~(0x01 << nbit);
+    if(op == WRITE_FUNCTION) 
+    {
+        if (state)
+        {
+            buf[nbyt] |= (0x01 << nbit);
+        }
+        else
+        {
+            buf[nbyt] &= ~(0x01 << nbit);
+        }
 
-      return 1;
-   }
-   else
-      return ((buf[nbyt] >> nbit) & 0x01);
+        return 1;
+    } 
+    else
+    {
+        return ((buf[nbyt] >> nbit) & 0x01);
+    }
 }
\ No newline at end of file