Nico Bollen / LIN

Dependents:   MBED_LIN_RGB_Master_Example

Revision:
8:63d341e53cce
Parent:
5:b42737f5dabc
--- a/LinMaster.cpp	Mon Jun 08 11:59:35 2020 +0000
+++ b/LinMaster.cpp	Mon Jun 15 12:42:04 2020 +0000
@@ -27,17 +27,16 @@
 
 const uint8_t breakPeriodMessage = 40;                      /* number of timer overflows in the break field during normal LIN messages */
 const uint8_t breakPeriodAcfg = 74;                         /* number of timer overflows in the break field during autoconfig messages */
-    
-LinMaster::LinMaster(PinName InPin, PinName OutPin) : LinOutPin(OutPin), LinInPin(InPin), LinIntPin(InPin)
+
+LinMaster::LinMaster(PinName InPin, PinName OutPin) : LinOutPin(OutPin), LinInPin(InPin, PullUp)
 {
-    this->DriverState  = INIT;
-    this->LastError    = NoError;
+    this->DriverState = INIT;
+    this->LastError = NoError;
     
     this->LinOutPin.write(1);
-    
-    this->LinInPin.mode(PullUp);
-    
-    this->LinIntPin.disable_irq();
+
+    this->LinInPin.disable_irq();
+    this->LinInPin.fall(NULL);
     
     this->DriverState = IDLE;
     
@@ -46,65 +45,66 @@
 
 LinMaster::~LinMaster()
 {
-    this->LinIntPin.disable_irq();
-    this->MyTicker.detach(); 
-    this->MyTimer.stop();
+    this->LinInPin.disable_irq();
+    this->LinInPin.fall(NULL);
+    this->HalfbitTicker.detach(); 
+    this->TimeoutTicker.detach();
 }
 
 bool LinMaster::init(void)
 {
     this->LinOutPin.write(1);
-    
-    this->LinInPin.mode(PullUp);
 
-    this->LinIntPin.disable_irq();
-    
+    this->LinInPin.enable_irq();
+    this->LinInPin.fall(NULL);
+
     this->DriverState = IDLE;
-    
+
     return ( true );
 }
 
 bool LinMaster::baudrate(uint16_t uBaud)
 {
     bool blReturn = false;
-    
+
     if ((uBaud > 0) && (uBaud <= 20000))
     {
-        this->u16HalfBitPeriod = 1000000/(2*uBaud);
+        this->u16HalfBitPeriod = std::chrono::microseconds(1000000 / ( 2 * uBaud));
         blReturn = true;
     }
-    
+
     return ( blReturn );
 }
 
 uint16_t LinMaster::baudrate(void)
 {
-    return ( 1000000 / (2 * this->u16HalfBitPeriod) );
+    return ( 1000000 / (2 * this->u16HalfBitPeriod.count()) );
 }
 
 bool LinMaster::send_frame(Frame_t * ptrFrame)
 {
     bool blReturn = false;
-    
+
     if ( (this->DriverState == IDLE) && (this->LinInPin.read() == 1) )
     {
         /* Clear and initialize all registers */
         memset(this->RXbuf, 0, 11);
-        
-        /* Disable half bit interrupt */
-        this->MyTicker.detach();
-        
-        this->LinIntPin.disable_irq();
-        
+
+        /* Disable ticker interrupt */
+        this->HalfbitTicker.detach();
+        this->TimeoutTicker.detach();
+
+        this->LinInPin.fall(NULL);
+
         this->LinOutPin.write(1);
-        
+
         this->DriverState = TRANSMIT;                       /* State of the LIN bus is transceiving a frame */
         this->LastError = NoError;
         this->FrameStatus = FStart;
         this->ByteStatus = BStart;
         this->RXbufIndex = 0;                               /* Reset index in the receiver buffer */
         this->TXbufIndex = 0;                               /* Reset index in the transmit buffer */
-    
+
         /* Set the correct brake-length */
         if (ptrFrame->Brake == AutoConfig)
         {
@@ -114,19 +114,19 @@
         {
             this->breakLength = breakPeriodMessage;
         }
-    
+
         this->FrameLength = 1 + 1 + ptrFrame->DataLen + 1;  /* Frame length = Sync + Frame ID + Data Len + CRC */
         this->linMessageType = ptrFrame->FrameType;
-    
+
         /* Create the correct frame buffer */
         this->TXbuf[0] = 0x55;                              /* Sync field */
         this->TXbuf[1] = this->parity(ptrFrame->FrameID);   /* Frame ID */
-    
+
         if (this->linMessageType == M2S)
         {
             uint16_t u16Crc;
             uint8_t i;
-            
+
             if (ptrFrame->CrcType == Enhanced)
             {
                 u16Crc = TXbuf[1];
@@ -135,7 +135,7 @@
             {
                 u16Crc = 0;
             }
-    
+
             for (i = 0; i < ptrFrame->DataLen; i++)
             {
                 this->TXbuf[i + 2] = ptrFrame->Data[i];     /* Data */
@@ -150,13 +150,14 @@
         else
         {
             /* S2M message */
-            this->RXtimeout = ((ptrFrame->DataLen + 1) * 14) * 2;   /* Calculate RX timeout in half bit-times */
-            this->RXtimeoutSubCTR = 0;
+
+            /* Calculate RX timeout */
+            this->FrameTimeout = std::chrono::microseconds(((ptrFrame->DataLen + 1) * 14) * 2 * this->u16HalfBitPeriod);
         }
-    
+
         /* Configure and start the half bit timer */
-        this->MyTicker.attach_us(this, &LinMaster::TickEventHndl, this->u16HalfBitPeriod);
-        
+        this->HalfbitTicker.attach(callback(this, &LinMaster::TickEventHndl), this->u16HalfBitPeriod);
+
         blReturn = true;
     }
     
@@ -205,6 +206,8 @@
 
 void LinMaster::TickEventHndl(void)
 {
+    int PinLevel = this->LinInPin.read();
+
     if (this->FrameStatus < Break_OK)
     {
         /* Do break field transmission */
@@ -235,11 +238,12 @@
         {
             /* No data needs to be transmitted */
             
-            /* Disable half bit interrupt */
-            this->MyTicker.detach();
+            /* Disable ticker interrupt */
+            this->HalfbitTicker.detach();
+            this->TimeoutTicker.detach();
             
             /* Disable LIN bus level interrupt */
-            this->LinIntPin.disable_irq();
+            this->LinInPin.fall(NULL);
         }
         else
         {
@@ -253,27 +257,11 @@
                     this->ByteStatus = static_cast<ByteStatus_t>(static_cast<int>(this->ByteStatus)+1);
                 }
 
-                if (this->RXtimeout > 0)
-                {
-                    this->RXtimeout--;
-                }
-                else
-                {
-                    this->DriverState = IDLE;
-                    this->LastError = NoSlaveResp;
-                    
-                    /* Disable half bit interrupt */
-                    this->MyTicker.detach();
-                    
-                    /* Disable LIN bus level interrupt */
-                    this->LinIntPin.disable_irq();
-                }
-
                 /* S2M message data receiving */
                 switch (this->ByteStatus)
                 {
                 case StartbitSample:
-                    if (LinInPin.read() == 0)
+                    if (PinLevel == 0)
                     {
                         /* OK */
                     }
@@ -294,43 +282,44 @@
                 case Databit7Sample:
                     /* Mid of single bit time, do sampling */
                     this->RXbuf[RXbufIndex] >>= 1;
-                    this->RXbuf[RXbufIndex] |= (LinInPin.read() << 7);
+                    this->RXbuf[RXbufIndex] |= (PinLevel << 7);
                     break;
 
                 case StopbitSample:
                     /* End of stop bit, stop Timer IRQ */
+
+                    /* Enable LIN bus level interrupt */
+                    this->LinInPin.fall(callback(this, &LinMaster::PinEventHndl));
+
+                    /* Disable half bit interrupt */
+                    this->HalfbitTicker.detach();
+
+                    /* Check the current bus level */
+                    if (PinLevel == 0)
+                    {
+                        this->LastError = FramingErr;       /* stop bit not valid => framing error */
+                    }
+
                     this->RXbufIndex++;
                     this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
                     this->ByteStatus = BStart;
 
-                    /* Check the current bus level */
-                    if (this->LinInPin.read() == 0)
-                    {
-                        this->LastError = FramingErr;       /* stop bit not valid => framing error */
-                    }
-
                     if ((this->RXbufIndex >= this->FrameLength) ||
                         (this->LastError != NoError))
                     {
                         /* All requested data bytes are received or an error occurred */
                         this->DriverState = IDLE;
                         
-                        /* Disable half bit interrupt */
-                        this->MyTicker.detach();
-                        
                         /* Disable LIN bus level interrupt */
-                        this->LinIntPin.disable_irq();
+                        this->LinInPin.fall(NULL);
+
+                        /* Disable timeout ticker */
+                        this->TimeoutTicker.detach();
                     }
                     else
                     {
                         /* Wait for a new data byte */
-                        this->MyTimer.start();
-                        
-                        /* Disable LIN bus level interrupt */
-                        this->LinIntPin.fall(this, &LinMaster::PinEventHndl);
-                        this->LinIntPin.enable_irq();
                     }
-
                     break;
                     
                 case Databit0Edge:
@@ -398,7 +387,7 @@
                 case Databit7Sample:
                     /* Odd overflow, mid of bit time ==> sample the bus for RX */
                     this->RXbuf[this->RXbufIndex] >>= 1;
-                    this->RXbuf[this->RXbufIndex] |= ((LinInPin.read() << 7) & 0x80);
+                    this->RXbuf[this->RXbufIndex] |= ((PinLevel << 7) & 0x80);
                     break;
 
                 case StopbitEdge:
@@ -408,54 +397,56 @@
 
                 case StopbitSample:
                     /* Stop bit : mid / level check */
-                    if (this->LinInPin.read() == 0)
+                    if (PinLevel == 0)
                     {
                         /* Stop bit not valid => framing error */
                         this->LastError = FramingErr;
                         this->DriverState = IDLE;
-                        
-                        /* Disable half bit interrupt */
-                        this->MyTicker.detach();
-                        
+
+                        /* Disable ticker interrupt */
+                        this->HalfbitTicker.detach();
+                        this->TimeoutTicker.detach();
+
                         /* Disable LIN bus level interrupt */
-                        this->LinIntPin.disable_irq();
+                        this->LinInPin.fall(NULL);
                     }
 
+                    this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
+                    this->TXbufIndex++;
+                    this->RXbufIndex++;
+
+                    if ((this->linMessageType == S2M) && (this->FrameStatus == ID_OK))
+                    {
+                        /* Stop bit of header is sent, now start receiving data bytes */
+
+                        /* Enable LIN bus level interrupt */
+                        this->LinInPin.fall(callback(this, &LinMaster::PinEventHndl));
+
+                        /* Disable half bit interrupt */
+                        this->HalfbitTicker.detach();
+
+                        /* Enable frame timeout interrupt */
+                        this->TimeoutTicker.attach(callback(this, &LinMaster::RXtimeoutEventHndl), this->FrameTimeout);
+                    }
                     break;
 
                 case BDone:
                     /* Stop bit : finished */
                     this->ByteStatus = BStart;
-                    this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
-                    this->TXbufIndex++;
-                    this->RXbufIndex++;
 
-                    if (this->linMessageType == S2M)
-                    {
-                        /* S2M frame */
-                        if (this->FrameStatus == ID_OK)
-                        {
-                            /* Stop bit of header is sent, now start receiving data bytes */
-                            this->MyTimer.start();
-                            
-                            /* Enable LIN bus level interrupt */
-                            this->LinIntPin.fall(this, &LinMaster::PinEventHndl);
-                            this->LinIntPin.enable_irq();
-                        }
-                    }
-                    else if (this->TXbufIndex >= this->FrameLength)
+                    if (this->TXbufIndex >= this->FrameLength)
                     {
                         /* M2S frame, Last byte is sent */
                         this->LastError = NoError;
                         this->DriverState = IDLE;
-                        
-                        /* Disable half bit interrupt */
-                        this->MyTicker.detach();
-                        
+
                         /* Disable LIN bus level interrupt */
-                        this->LinIntPin.disable_irq();
+                        this->LinInPin.fall(NULL);
+
+                        /* Disable ticker interrupts */
+                        this->TimeoutTicker.detach();
+                        this->HalfbitTicker.detach();
                     }
-
                     break;
 
                 default:
@@ -466,6 +457,19 @@
     }
 }
 
+void LinMaster::RXtimeoutEventHndl(void)
+{
+    /* Disable LIN bus level interrupt */
+    this->LinInPin.fall(NULL);
+
+    /* Disable half bit interrupt */
+    this->HalfbitTicker.detach();
+    this->TimeoutTicker.detach();
+
+    this->DriverState = IDLE;
+    this->LastError = NoSlaveResp;
+}
+
 void LinMaster::PinEventHndl(void)
 {
     switch (this->DriverState)
@@ -473,29 +477,16 @@
     case TRANSMIT:
     case RECEIVE:
     {
-        this->ByteStatus = StartbitEdge;                    /* Set status of the received byte */
-        this->RXtimeoutSubCTR += this->MyTimer.read_us();
-        this->MyTimer.stop();
-        
+        this->ByteStatus = StartbitSample;                  /* Set status of the received byte */
+
         /* Reset ticker */
-        this->MyTicker.detach();
-        this->MyTicker.attach_us(this, &LinMaster::TickEventHndl, this->u16HalfBitPeriod);
-        
+        this->HalfbitTicker.attach(callback(this, &LinMaster::TickEventHndl), this->u16HalfBitPeriod);
+
         /* Disable LIN bus level interrupt */
-        this->LinIntPin.disable_irq();
-
-        if (this->RXtimeoutSubCTR > this->u16HalfBitPeriod)
-        {
-            this->RXtimeoutSubCTR -= this->u16HalfBitPeriod;
-            if (this->RXtimeout > 0)
-            {
-                this->RXtimeout--;
-            }
-        }
-
+        this->LinInPin.fall(NULL);
         break;
     }
-    
+
     case IDLE:
     case DOMINANT:
     case TXWAKEUP: