Nico Bollen / LIN

Dependents:   MBED_LIN_RGB_Master_Example

Committer:
bollenn
Date:
Mon Jun 15 12:42:04 2020 +0000
Revision:
8:63d341e53cce
Parent:
5:b42737f5dabc
Rework receive path

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bollenn 1:58b5d1e8fae3 1 /*
bollenn 0:c91a9ebab739 2 * Master device LIN communication library for mbed
bollenn 0:c91a9ebab739 3 *
bollenn 4:41b153e9a39c 4 * Copyright (C) 2015 Bollen Nico
bollenn 0:c91a9ebab739 5 *
bollenn 0:c91a9ebab739 6 * Released under GPL v2
bollenn 0:c91a9ebab739 7 *
bollenn 0:c91a9ebab739 8 * Other licensing models might apply at the sole discretion of the copyright holders.
bollenn 0:c91a9ebab739 9 *
bollenn 0:c91a9ebab739 10 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
bollenn 0:c91a9ebab739 11 * and associated documentation files (the "Software"), to deal in the Software without restriction,
bollenn 0:c91a9ebab739 12 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
bollenn 0:c91a9ebab739 13 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
bollenn 0:c91a9ebab739 14 * furnished to do so, subject to the following conditions:
bollenn 0:c91a9ebab739 15 *
bollenn 0:c91a9ebab739 16 * The above copyright notice and this permission notice shall be included in all copies or
bollenn 0:c91a9ebab739 17 * substantial portions of the Software.
bollenn 0:c91a9ebab739 18 *
bollenn 0:c91a9ebab739 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
bollenn 0:c91a9ebab739 20 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
bollenn 0:c91a9ebab739 21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
bollenn 0:c91a9ebab739 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
bollenn 0:c91a9ebab739 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bollenn 0:c91a9ebab739 24 */
bollenn 0:c91a9ebab739 25
bollenn 0:c91a9ebab739 26 #include "LinMaster.h"
bollenn 0:c91a9ebab739 27
bollenn 3:3656b0de0e43 28 const uint8_t breakPeriodMessage = 40; /* number of timer overflows in the break field during normal LIN messages */
bollenn 3:3656b0de0e43 29 const uint8_t breakPeriodAcfg = 74; /* number of timer overflows in the break field during autoconfig messages */
bollenn 8:63d341e53cce 30
bollenn 8:63d341e53cce 31 LinMaster::LinMaster(PinName InPin, PinName OutPin) : LinOutPin(OutPin), LinInPin(InPin, PullUp)
bollenn 0:c91a9ebab739 32 {
bollenn 8:63d341e53cce 33 this->DriverState = INIT;
bollenn 8:63d341e53cce 34 this->LastError = NoError;
bollenn 4:41b153e9a39c 35
bollenn 4:41b153e9a39c 36 this->LinOutPin.write(1);
bollenn 8:63d341e53cce 37
bollenn 8:63d341e53cce 38 this->LinInPin.disable_irq();
bollenn 8:63d341e53cce 39 this->LinInPin.fall(NULL);
bollenn 4:41b153e9a39c 40
bollenn 4:41b153e9a39c 41 this->DriverState = IDLE;
bollenn 4:41b153e9a39c 42
bollenn 3:3656b0de0e43 43 (void)this->baudrate(9600);
bollenn 0:c91a9ebab739 44 }
bollenn 0:c91a9ebab739 45
bollenn 0:c91a9ebab739 46 LinMaster::~LinMaster()
bollenn 0:c91a9ebab739 47 {
bollenn 8:63d341e53cce 48 this->LinInPin.disable_irq();
bollenn 8:63d341e53cce 49 this->LinInPin.fall(NULL);
bollenn 8:63d341e53cce 50 this->HalfbitTicker.detach();
bollenn 8:63d341e53cce 51 this->TimeoutTicker.detach();
bollenn 0:c91a9ebab739 52 }
bollenn 0:c91a9ebab739 53
bollenn 3:3656b0de0e43 54 bool LinMaster::init(void)
bollenn 0:c91a9ebab739 55 {
bollenn 4:41b153e9a39c 56 this->LinOutPin.write(1);
bollenn 5:b42737f5dabc 57
bollenn 8:63d341e53cce 58 this->LinInPin.enable_irq();
bollenn 8:63d341e53cce 59 this->LinInPin.fall(NULL);
bollenn 8:63d341e53cce 60
bollenn 3:3656b0de0e43 61 this->DriverState = IDLE;
bollenn 8:63d341e53cce 62
bollenn 0:c91a9ebab739 63 return ( true );
bollenn 0:c91a9ebab739 64 }
bollenn 0:c91a9ebab739 65
bollenn 3:3656b0de0e43 66 bool LinMaster::baudrate(uint16_t uBaud)
bollenn 0:c91a9ebab739 67 {
bollenn 0:c91a9ebab739 68 bool blReturn = false;
bollenn 8:63d341e53cce 69
bollenn 0:c91a9ebab739 70 if ((uBaud > 0) && (uBaud <= 20000))
bollenn 0:c91a9ebab739 71 {
bollenn 8:63d341e53cce 72 this->u16HalfBitPeriod = std::chrono::microseconds(1000000 / ( 2 * uBaud));
bollenn 0:c91a9ebab739 73 blReturn = true;
bollenn 0:c91a9ebab739 74 }
bollenn 8:63d341e53cce 75
bollenn 0:c91a9ebab739 76 return ( blReturn );
bollenn 0:c91a9ebab739 77 }
bollenn 0:c91a9ebab739 78
bollenn 3:3656b0de0e43 79 uint16_t LinMaster::baudrate(void)
bollenn 0:c91a9ebab739 80 {
bollenn 8:63d341e53cce 81 return ( 1000000 / (2 * this->u16HalfBitPeriod.count()) );
bollenn 0:c91a9ebab739 82 }
bollenn 0:c91a9ebab739 83
bollenn 4:41b153e9a39c 84 bool LinMaster::send_frame(Frame_t * ptrFrame)
bollenn 0:c91a9ebab739 85 {
bollenn 2:6d4c7f841a5d 86 bool blReturn = false;
bollenn 8:63d341e53cce 87
bollenn 4:41b153e9a39c 88 if ( (this->DriverState == IDLE) && (this->LinInPin.read() == 1) )
bollenn 2:6d4c7f841a5d 89 {
bollenn 3:3656b0de0e43 90 /* Clear and initialize all registers */
bollenn 5:b42737f5dabc 91 memset(this->RXbuf, 0, 11);
bollenn 8:63d341e53cce 92
bollenn 8:63d341e53cce 93 /* Disable ticker interrupt */
bollenn 8:63d341e53cce 94 this->HalfbitTicker.detach();
bollenn 8:63d341e53cce 95 this->TimeoutTicker.detach();
bollenn 8:63d341e53cce 96
bollenn 8:63d341e53cce 97 this->LinInPin.fall(NULL);
bollenn 8:63d341e53cce 98
bollenn 4:41b153e9a39c 99 this->LinOutPin.write(1);
bollenn 8:63d341e53cce 100
bollenn 3:3656b0de0e43 101 this->DriverState = TRANSMIT; /* State of the LIN bus is transceiving a frame */
bollenn 3:3656b0de0e43 102 this->LastError = NoError;
bollenn 3:3656b0de0e43 103 this->FrameStatus = FStart;
bollenn 3:3656b0de0e43 104 this->ByteStatus = BStart;
bollenn 3:3656b0de0e43 105 this->RXbufIndex = 0; /* Reset index in the receiver buffer */
bollenn 3:3656b0de0e43 106 this->TXbufIndex = 0; /* Reset index in the transmit buffer */
bollenn 8:63d341e53cce 107
bollenn 3:3656b0de0e43 108 /* Set the correct brake-length */
bollenn 3:3656b0de0e43 109 if (ptrFrame->Brake == AutoConfig)
bollenn 3:3656b0de0e43 110 {
bollenn 3:3656b0de0e43 111 this->breakLength = breakPeriodAcfg;
bollenn 3:3656b0de0e43 112 }
bollenn 3:3656b0de0e43 113 else
bollenn 3:3656b0de0e43 114 {
bollenn 3:3656b0de0e43 115 this->breakLength = breakPeriodMessage;
bollenn 3:3656b0de0e43 116 }
bollenn 8:63d341e53cce 117
bollenn 3:3656b0de0e43 118 this->FrameLength = 1 + 1 + ptrFrame->DataLen + 1; /* Frame length = Sync + Frame ID + Data Len + CRC */
bollenn 3:3656b0de0e43 119 this->linMessageType = ptrFrame->FrameType;
bollenn 8:63d341e53cce 120
bollenn 3:3656b0de0e43 121 /* Create the correct frame buffer */
bollenn 3:3656b0de0e43 122 this->TXbuf[0] = 0x55; /* Sync field */
bollenn 3:3656b0de0e43 123 this->TXbuf[1] = this->parity(ptrFrame->FrameID); /* Frame ID */
bollenn 8:63d341e53cce 124
bollenn 3:3656b0de0e43 125 if (this->linMessageType == M2S)
bollenn 3:3656b0de0e43 126 {
bollenn 3:3656b0de0e43 127 uint16_t u16Crc;
bollenn 3:3656b0de0e43 128 uint8_t i;
bollenn 8:63d341e53cce 129
bollenn 3:3656b0de0e43 130 if (ptrFrame->CrcType == Enhanced)
bollenn 3:3656b0de0e43 131 {
bollenn 3:3656b0de0e43 132 u16Crc = TXbuf[1];
bollenn 3:3656b0de0e43 133 }
bollenn 3:3656b0de0e43 134 else
bollenn 3:3656b0de0e43 135 {
bollenn 3:3656b0de0e43 136 u16Crc = 0;
bollenn 3:3656b0de0e43 137 }
bollenn 8:63d341e53cce 138
bollenn 3:3656b0de0e43 139 for (i = 0; i < ptrFrame->DataLen; i++)
bollenn 3:3656b0de0e43 140 {
bollenn 3:3656b0de0e43 141 this->TXbuf[i + 2] = ptrFrame->Data[i]; /* Data */
bollenn 3:3656b0de0e43 142 u16Crc += ptrFrame->Data[i];
bollenn 3:3656b0de0e43 143 if (u16Crc >= 256)
bollenn 3:3656b0de0e43 144 {
bollenn 3:3656b0de0e43 145 u16Crc -= 255;
bollenn 3:3656b0de0e43 146 }
bollenn 3:3656b0de0e43 147 }
bollenn 3:3656b0de0e43 148 this->TXbuf[ptrFrame->DataLen + 2] = (uint8_t)(~u16Crc);
bollenn 3:3656b0de0e43 149 }
bollenn 3:3656b0de0e43 150 else
bollenn 3:3656b0de0e43 151 {
bollenn 3:3656b0de0e43 152 /* S2M message */
bollenn 8:63d341e53cce 153
bollenn 8:63d341e53cce 154 /* Calculate RX timeout */
bollenn 8:63d341e53cce 155 this->FrameTimeout = std::chrono::microseconds(((ptrFrame->DataLen + 1) * 14) * 2 * this->u16HalfBitPeriod);
bollenn 3:3656b0de0e43 156 }
bollenn 8:63d341e53cce 157
bollenn 3:3656b0de0e43 158 /* Configure and start the half bit timer */
bollenn 8:63d341e53cce 159 this->HalfbitTicker.attach(callback(this, &LinMaster::TickEventHndl), this->u16HalfBitPeriod);
bollenn 8:63d341e53cce 160
bollenn 2:6d4c7f841a5d 161 blReturn = true;
bollenn 2:6d4c7f841a5d 162 }
bollenn 2:6d4c7f841a5d 163
bollenn 2:6d4c7f841a5d 164 return ( blReturn );
bollenn 2:6d4c7f841a5d 165 }
bollenn 2:6d4c7f841a5d 166
bollenn 5:b42737f5dabc 167 bool LinMaster::get_rx_data(Frame_t &ptrFrame)
bollenn 3:3656b0de0e43 168 {
bollenn 3:3656b0de0e43 169 uint16_t u16Crc;
bollenn 3:3656b0de0e43 170 uint8_t i;
bollenn 3:3656b0de0e43 171
bollenn 4:41b153e9a39c 172 if ( (this->DriverState != IDLE) || (this->LastError != NoError))
bollenn 3:3656b0de0e43 173 {
bollenn 3:3656b0de0e43 174 return (false);
bollenn 3:3656b0de0e43 175 }
bollenn 3:3656b0de0e43 176
bollenn 3:3656b0de0e43 177 /* Copy data and check RX frame CRC */
bollenn 5:b42737f5dabc 178 if (ptrFrame.CrcType == Enhanced)
bollenn 3:3656b0de0e43 179 {
bollenn 3:3656b0de0e43 180 u16Crc = RXbuf[1];
bollenn 3:3656b0de0e43 181 }
bollenn 3:3656b0de0e43 182 else
bollenn 3:3656b0de0e43 183 {
bollenn 3:3656b0de0e43 184 u16Crc = 0;
bollenn 3:3656b0de0e43 185 }
bollenn 3:3656b0de0e43 186
bollenn 5:b42737f5dabc 187 for (i = 0; i < ptrFrame.DataLen; i++)
bollenn 3:3656b0de0e43 188 {
bollenn 5:b42737f5dabc 189 ptrFrame.Data[i] = RXbuf[1 + 1 + i];
bollenn 3:3656b0de0e43 190 u16Crc += RXbuf[1 + 1 + i];
bollenn 3:3656b0de0e43 191 if (u16Crc >= 256)
bollenn 3:3656b0de0e43 192 {
bollenn 3:3656b0de0e43 193 u16Crc -= 255;
bollenn 3:3656b0de0e43 194 }
bollenn 3:3656b0de0e43 195 }
bollenn 3:3656b0de0e43 196
bollenn 5:b42737f5dabc 197 if (this->RXbuf[ptrFrame.DataLen + 2] == (uint8_t)(~u16Crc))
bollenn 3:3656b0de0e43 198 {
bollenn 3:3656b0de0e43 199 return (true);
bollenn 3:3656b0de0e43 200 }
bollenn 3:3656b0de0e43 201 else
bollenn 3:3656b0de0e43 202 {
bollenn 3:3656b0de0e43 203 return (false);
bollenn 3:3656b0de0e43 204 }
bollenn 3:3656b0de0e43 205 }
bollenn 3:3656b0de0e43 206
bollenn 2:6d4c7f841a5d 207 void LinMaster::TickEventHndl(void)
bollenn 2:6d4c7f841a5d 208 {
bollenn 8:63d341e53cce 209 int PinLevel = this->LinInPin.read();
bollenn 8:63d341e53cce 210
bollenn 3:3656b0de0e43 211 if (this->FrameStatus < Break_OK)
bollenn 2:6d4c7f841a5d 212 {
bollenn 3:3656b0de0e43 213 /* Do break field transmission */
bollenn 3:3656b0de0e43 214 if (this->breakLength > 2)
bollenn 3:3656b0de0e43 215 {
bollenn 3:3656b0de0e43 216 /* Dominant Level */
bollenn 4:41b153e9a39c 217 this->LinOutPin.write(0);
bollenn 3:3656b0de0e43 218 }
bollenn 3:3656b0de0e43 219 else
bollenn 3:3656b0de0e43 220 {
bollenn 3:3656b0de0e43 221 /* Recessive Level */
bollenn 4:41b153e9a39c 222 this->LinOutPin.write(1);
bollenn 3:3656b0de0e43 223 }
bollenn 3:3656b0de0e43 224
bollenn 3:3656b0de0e43 225 if (this->breakLength > 0)
bollenn 3:3656b0de0e43 226 {
bollenn 3:3656b0de0e43 227 this->breakLength--;
bollenn 3:3656b0de0e43 228 }
bollenn 3:3656b0de0e43 229 else
bollenn 3:3656b0de0e43 230 {
bollenn 3:3656b0de0e43 231 this->FrameStatus = Break_OK;
bollenn 3:3656b0de0e43 232 }
bollenn 2:6d4c7f841a5d 233 }
bollenn 2:6d4c7f841a5d 234 else
bollenn 2:6d4c7f841a5d 235 {
bollenn 3:3656b0de0e43 236 /* Break field was transmitted */
bollenn 3:3656b0de0e43 237 if (this->FrameLength == 0)
bollenn 2:6d4c7f841a5d 238 {
bollenn 3:3656b0de0e43 239 /* No data needs to be transmitted */
bollenn 3:3656b0de0e43 240
bollenn 8:63d341e53cce 241 /* Disable ticker interrupt */
bollenn 8:63d341e53cce 242 this->HalfbitTicker.detach();
bollenn 8:63d341e53cce 243 this->TimeoutTicker.detach();
bollenn 3:3656b0de0e43 244
bollenn 3:3656b0de0e43 245 /* Disable LIN bus level interrupt */
bollenn 8:63d341e53cce 246 this->LinInPin.fall(NULL);
bollenn 2:6d4c7f841a5d 247 }
bollenn 3:3656b0de0e43 248 else
bollenn 2:6d4c7f841a5d 249 {
bollenn 3:3656b0de0e43 250 /* Data needs to be transmitted or received */
bollenn 3:3656b0de0e43 251 if ( (this->linMessageType == S2M) &&
bollenn 3:3656b0de0e43 252 (this->FrameStatus >= ID_OK))
bollenn 2:6d4c7f841a5d 253 {
bollenn 3:3656b0de0e43 254 if (this->ByteStatus > BStart)
bollenn 3:3656b0de0e43 255 {
bollenn 3:3656b0de0e43 256 /* Not waiting for start bit */
bollenn 3:3656b0de0e43 257 this->ByteStatus = static_cast<ByteStatus_t>(static_cast<int>(this->ByteStatus)+1);
bollenn 3:3656b0de0e43 258 }
bollenn 3:3656b0de0e43 259
bollenn 3:3656b0de0e43 260 /* S2M message data receiving */
bollenn 3:3656b0de0e43 261 switch (this->ByteStatus)
bollenn 3:3656b0de0e43 262 {
bollenn 3:3656b0de0e43 263 case StartbitSample:
bollenn 8:63d341e53cce 264 if (PinLevel == 0)
bollenn 3:3656b0de0e43 265 {
bollenn 3:3656b0de0e43 266 /* OK */
bollenn 3:3656b0de0e43 267 }
bollenn 3:3656b0de0e43 268 else
bollenn 3:3656b0de0e43 269 {
bollenn 3:3656b0de0e43 270 /* TODO error */
bollenn 3:3656b0de0e43 271 }
bollenn 3:3656b0de0e43 272
bollenn 3:3656b0de0e43 273 break;
bollenn 3:3656b0de0e43 274
bollenn 3:3656b0de0e43 275 case Databit0Sample:
bollenn 3:3656b0de0e43 276 case Databit1Sample:
bollenn 3:3656b0de0e43 277 case Databit2Sample:
bollenn 3:3656b0de0e43 278 case Databit3Sample:
bollenn 3:3656b0de0e43 279 case Databit4Sample:
bollenn 3:3656b0de0e43 280 case Databit5Sample:
bollenn 3:3656b0de0e43 281 case Databit6Sample:
bollenn 3:3656b0de0e43 282 case Databit7Sample:
bollenn 3:3656b0de0e43 283 /* Mid of single bit time, do sampling */
bollenn 3:3656b0de0e43 284 this->RXbuf[RXbufIndex] >>= 1;
bollenn 8:63d341e53cce 285 this->RXbuf[RXbufIndex] |= (PinLevel << 7);
bollenn 3:3656b0de0e43 286 break;
bollenn 3:3656b0de0e43 287
bollenn 3:3656b0de0e43 288 case StopbitSample:
bollenn 3:3656b0de0e43 289 /* End of stop bit, stop Timer IRQ */
bollenn 8:63d341e53cce 290
bollenn 8:63d341e53cce 291 /* Enable LIN bus level interrupt */
bollenn 8:63d341e53cce 292 this->LinInPin.fall(callback(this, &LinMaster::PinEventHndl));
bollenn 8:63d341e53cce 293
bollenn 8:63d341e53cce 294 /* Disable half bit interrupt */
bollenn 8:63d341e53cce 295 this->HalfbitTicker.detach();
bollenn 8:63d341e53cce 296
bollenn 8:63d341e53cce 297 /* Check the current bus level */
bollenn 8:63d341e53cce 298 if (PinLevel == 0)
bollenn 8:63d341e53cce 299 {
bollenn 8:63d341e53cce 300 this->LastError = FramingErr; /* stop bit not valid => framing error */
bollenn 8:63d341e53cce 301 }
bollenn 8:63d341e53cce 302
bollenn 3:3656b0de0e43 303 this->RXbufIndex++;
bollenn 3:3656b0de0e43 304 this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
bollenn 3:3656b0de0e43 305 this->ByteStatus = BStart;
bollenn 3:3656b0de0e43 306
bollenn 3:3656b0de0e43 307 if ((this->RXbufIndex >= this->FrameLength) ||
bollenn 3:3656b0de0e43 308 (this->LastError != NoError))
bollenn 3:3656b0de0e43 309 {
bollenn 3:3656b0de0e43 310 /* All requested data bytes are received or an error occurred */
bollenn 3:3656b0de0e43 311 this->DriverState = IDLE;
bollenn 3:3656b0de0e43 312
bollenn 3:3656b0de0e43 313 /* Disable LIN bus level interrupt */
bollenn 8:63d341e53cce 314 this->LinInPin.fall(NULL);
bollenn 8:63d341e53cce 315
bollenn 8:63d341e53cce 316 /* Disable timeout ticker */
bollenn 8:63d341e53cce 317 this->TimeoutTicker.detach();
bollenn 3:3656b0de0e43 318 }
bollenn 3:3656b0de0e43 319 else
bollenn 3:3656b0de0e43 320 {
bollenn 3:3656b0de0e43 321 /* Wait for a new data byte */
bollenn 3:3656b0de0e43 322 }
bollenn 3:3656b0de0e43 323 break;
bollenn 5:b42737f5dabc 324
bollenn 3:3656b0de0e43 325 case Databit0Edge:
bollenn 3:3656b0de0e43 326 case Databit1Edge:
bollenn 3:3656b0de0e43 327 case Databit2Edge:
bollenn 3:3656b0de0e43 328 case Databit3Edge:
bollenn 3:3656b0de0e43 329 case Databit4Edge:
bollenn 3:3656b0de0e43 330 case Databit5Edge:
bollenn 3:3656b0de0e43 331 case Databit6Edge:
bollenn 3:3656b0de0e43 332 case Databit7Edge:
bollenn 3:3656b0de0e43 333 case StopbitEdge:
bollenn 3:3656b0de0e43 334 case BDone:
bollenn 3:3656b0de0e43 335 case BStart:
bollenn 3:3656b0de0e43 336 default:
bollenn 3:3656b0de0e43 337 /* Do nothing */
bollenn 3:3656b0de0e43 338 break;
bollenn 3:3656b0de0e43 339 }
bollenn 2:6d4c7f841a5d 340 }
bollenn 2:6d4c7f841a5d 341 else
bollenn 2:6d4c7f841a5d 342 {
bollenn 3:3656b0de0e43 343 /* Transmission of Sync + Frame ID and M2S frame data */
bollenn 3:3656b0de0e43 344 this->ByteStatus = static_cast<ByteStatus_t>(static_cast<int>(this->ByteStatus)+1);
bollenn 3:3656b0de0e43 345
bollenn 3:3656b0de0e43 346 switch (this->ByteStatus)
bollenn 3:3656b0de0e43 347 {
bollenn 3:3656b0de0e43 348 case StartbitEdge:
bollenn 3:3656b0de0e43 349 /* Start bit : start */
bollenn 4:41b153e9a39c 350 this->LinOutPin.write(0);
bollenn 3:3656b0de0e43 351 break;
bollenn 3:3656b0de0e43 352
bollenn 3:3656b0de0e43 353 case StartbitSample:
bollenn 3:3656b0de0e43 354 /* Start bit : mid */
bollenn 3:3656b0de0e43 355 break;
bollenn 3:3656b0de0e43 356
bollenn 3:3656b0de0e43 357 case Databit0Edge:
bollenn 3:3656b0de0e43 358 case Databit1Edge:
bollenn 3:3656b0de0e43 359 case Databit2Edge:
bollenn 3:3656b0de0e43 360 case Databit3Edge:
bollenn 3:3656b0de0e43 361 case Databit4Edge:
bollenn 3:3656b0de0e43 362 case Databit5Edge:
bollenn 3:3656b0de0e43 363 case Databit6Edge:
bollenn 3:3656b0de0e43 364 case Databit7Edge:
bollenn 3:3656b0de0e43 365 /* Start of new bit time */
bollenn 3:3656b0de0e43 366 if (this->TXbuf[this->TXbufIndex] & 0x01)
bollenn 3:3656b0de0e43 367 {
bollenn 3:3656b0de0e43 368 /* Recessive Level */
bollenn 4:41b153e9a39c 369 this->LinOutPin.write(1);
bollenn 3:3656b0de0e43 370 }
bollenn 3:3656b0de0e43 371 else
bollenn 3:3656b0de0e43 372 {
bollenn 3:3656b0de0e43 373 /* Dominant Level */
bollenn 4:41b153e9a39c 374 this->LinOutPin.write(0);
bollenn 3:3656b0de0e43 375 }
bollenn 3:3656b0de0e43 376
bollenn 3:3656b0de0e43 377 this->TXbuf[this->TXbufIndex] >>= 1;
bollenn 3:3656b0de0e43 378 break;
bollenn 3:3656b0de0e43 379
bollenn 3:3656b0de0e43 380 case Databit0Sample:
bollenn 3:3656b0de0e43 381 case Databit1Sample:
bollenn 3:3656b0de0e43 382 case Databit2Sample:
bollenn 3:3656b0de0e43 383 case Databit3Sample:
bollenn 3:3656b0de0e43 384 case Databit4Sample:
bollenn 3:3656b0de0e43 385 case Databit5Sample:
bollenn 3:3656b0de0e43 386 case Databit6Sample:
bollenn 3:3656b0de0e43 387 case Databit7Sample:
bollenn 3:3656b0de0e43 388 /* Odd overflow, mid of bit time ==> sample the bus for RX */
bollenn 3:3656b0de0e43 389 this->RXbuf[this->RXbufIndex] >>= 1;
bollenn 8:63d341e53cce 390 this->RXbuf[this->RXbufIndex] |= ((PinLevel << 7) & 0x80);
bollenn 3:3656b0de0e43 391 break;
bollenn 3:3656b0de0e43 392
bollenn 3:3656b0de0e43 393 case StopbitEdge:
bollenn 3:3656b0de0e43 394 /* Stop bit : start */
bollenn 4:41b153e9a39c 395 this->LinOutPin.write(1);
bollenn 3:3656b0de0e43 396 break;
bollenn 2:6d4c7f841a5d 397
bollenn 3:3656b0de0e43 398 case StopbitSample:
bollenn 3:3656b0de0e43 399 /* Stop bit : mid / level check */
bollenn 8:63d341e53cce 400 if (PinLevel == 0)
bollenn 3:3656b0de0e43 401 {
bollenn 3:3656b0de0e43 402 /* Stop bit not valid => framing error */
bollenn 3:3656b0de0e43 403 this->LastError = FramingErr;
bollenn 3:3656b0de0e43 404 this->DriverState = IDLE;
bollenn 8:63d341e53cce 405
bollenn 8:63d341e53cce 406 /* Disable ticker interrupt */
bollenn 8:63d341e53cce 407 this->HalfbitTicker.detach();
bollenn 8:63d341e53cce 408 this->TimeoutTicker.detach();
bollenn 8:63d341e53cce 409
bollenn 3:3656b0de0e43 410 /* Disable LIN bus level interrupt */
bollenn 8:63d341e53cce 411 this->LinInPin.fall(NULL);
bollenn 3:3656b0de0e43 412 }
bollenn 3:3656b0de0e43 413
bollenn 8:63d341e53cce 414 this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
bollenn 8:63d341e53cce 415 this->TXbufIndex++;
bollenn 8:63d341e53cce 416 this->RXbufIndex++;
bollenn 8:63d341e53cce 417
bollenn 8:63d341e53cce 418 if ((this->linMessageType == S2M) && (this->FrameStatus == ID_OK))
bollenn 8:63d341e53cce 419 {
bollenn 8:63d341e53cce 420 /* Stop bit of header is sent, now start receiving data bytes */
bollenn 8:63d341e53cce 421
bollenn 8:63d341e53cce 422 /* Enable LIN bus level interrupt */
bollenn 8:63d341e53cce 423 this->LinInPin.fall(callback(this, &LinMaster::PinEventHndl));
bollenn 8:63d341e53cce 424
bollenn 8:63d341e53cce 425 /* Disable half bit interrupt */
bollenn 8:63d341e53cce 426 this->HalfbitTicker.detach();
bollenn 8:63d341e53cce 427
bollenn 8:63d341e53cce 428 /* Enable frame timeout interrupt */
bollenn 8:63d341e53cce 429 this->TimeoutTicker.attach(callback(this, &LinMaster::RXtimeoutEventHndl), this->FrameTimeout);
bollenn 8:63d341e53cce 430 }
bollenn 3:3656b0de0e43 431 break;
bollenn 3:3656b0de0e43 432
bollenn 3:3656b0de0e43 433 case BDone:
bollenn 3:3656b0de0e43 434 /* Stop bit : finished */
bollenn 3:3656b0de0e43 435 this->ByteStatus = BStart;
bollenn 3:3656b0de0e43 436
bollenn 8:63d341e53cce 437 if (this->TXbufIndex >= this->FrameLength)
bollenn 3:3656b0de0e43 438 {
bollenn 3:3656b0de0e43 439 /* M2S frame, Last byte is sent */
bollenn 3:3656b0de0e43 440 this->LastError = NoError;
bollenn 3:3656b0de0e43 441 this->DriverState = IDLE;
bollenn 8:63d341e53cce 442
bollenn 3:3656b0de0e43 443 /* Disable LIN bus level interrupt */
bollenn 8:63d341e53cce 444 this->LinInPin.fall(NULL);
bollenn 8:63d341e53cce 445
bollenn 8:63d341e53cce 446 /* Disable ticker interrupts */
bollenn 8:63d341e53cce 447 this->TimeoutTicker.detach();
bollenn 8:63d341e53cce 448 this->HalfbitTicker.detach();
bollenn 3:3656b0de0e43 449 }
bollenn 3:3656b0de0e43 450 break;
bollenn 3:3656b0de0e43 451
bollenn 3:3656b0de0e43 452 default:
bollenn 3:3656b0de0e43 453 break;
bollenn 3:3656b0de0e43 454 }
bollenn 2:6d4c7f841a5d 455 }
bollenn 2:6d4c7f841a5d 456 }
bollenn 2:6d4c7f841a5d 457 }
bollenn 0:c91a9ebab739 458 }
bollenn 0:c91a9ebab739 459
bollenn 8:63d341e53cce 460 void LinMaster::RXtimeoutEventHndl(void)
bollenn 8:63d341e53cce 461 {
bollenn 8:63d341e53cce 462 /* Disable LIN bus level interrupt */
bollenn 8:63d341e53cce 463 this->LinInPin.fall(NULL);
bollenn 8:63d341e53cce 464
bollenn 8:63d341e53cce 465 /* Disable half bit interrupt */
bollenn 8:63d341e53cce 466 this->HalfbitTicker.detach();
bollenn 8:63d341e53cce 467 this->TimeoutTicker.detach();
bollenn 8:63d341e53cce 468
bollenn 8:63d341e53cce 469 this->DriverState = IDLE;
bollenn 8:63d341e53cce 470 this->LastError = NoSlaveResp;
bollenn 8:63d341e53cce 471 }
bollenn 8:63d341e53cce 472
bollenn 3:3656b0de0e43 473 void LinMaster::PinEventHndl(void)
bollenn 3:3656b0de0e43 474 {
bollenn 3:3656b0de0e43 475 switch (this->DriverState)
bollenn 3:3656b0de0e43 476 {
bollenn 3:3656b0de0e43 477 case TRANSMIT:
bollenn 3:3656b0de0e43 478 case RECEIVE:
bollenn 3:3656b0de0e43 479 {
bollenn 8:63d341e53cce 480 this->ByteStatus = StartbitSample; /* Set status of the received byte */
bollenn 8:63d341e53cce 481
bollenn 3:3656b0de0e43 482 /* Reset ticker */
bollenn 8:63d341e53cce 483 this->HalfbitTicker.attach(callback(this, &LinMaster::TickEventHndl), this->u16HalfBitPeriod);
bollenn 8:63d341e53cce 484
bollenn 3:3656b0de0e43 485 /* Disable LIN bus level interrupt */
bollenn 8:63d341e53cce 486 this->LinInPin.fall(NULL);
bollenn 3:3656b0de0e43 487 break;
bollenn 3:3656b0de0e43 488 }
bollenn 8:63d341e53cce 489
bollenn 3:3656b0de0e43 490 case IDLE:
bollenn 3:3656b0de0e43 491 case DOMINANT:
bollenn 3:3656b0de0e43 492 case TXWAKEUP:
bollenn 3:3656b0de0e43 493 break;
bollenn 3:3656b0de0e43 494
bollenn 3:3656b0de0e43 495 case RXWAKEUP:
bollenn 3:3656b0de0e43 496 default:
bollenn 3:3656b0de0e43 497 this->DriverState = RXWAKEUP; /* It's a wake up pulse */
bollenn 3:3656b0de0e43 498 break;
bollenn 3:3656b0de0e43 499 }
bollenn 3:3656b0de0e43 500 }
bollenn 3:3656b0de0e43 501
bollenn 3:3656b0de0e43 502 /** Calculate the parity bits
bollenn 3:3656b0de0e43 503 *
bollenn 3:3656b0de0e43 504 * @param u8BYTE original byte
bollenn 3:3656b0de0e43 505 * @return BYTE including parity bits
bollenn 3:3656b0de0e43 506 */
bollenn 3:3656b0de0e43 507 uint8_t LinMaster::parity(uint8_t u8BYTE)
bollenn 3:3656b0de0e43 508 {
bollenn 3:3656b0de0e43 509 uint8_t P0 = 0;
bollenn 3:3656b0de0e43 510 uint8_t P1 = 0;
bollenn 3:3656b0de0e43 511
bollenn 3:3656b0de0e43 512 /* P0 = ID0 + ID1 + ID2 + ID4
bollenn 3:3656b0de0e43 513 * P1 = ~(ID1 + ID3 + ID4 + ID5)
bollenn 3:3656b0de0e43 514 */
bollenn 3:3656b0de0e43 515 if ((u8BYTE & (1 << 0)) != 0)
bollenn 3:3656b0de0e43 516 {
bollenn 3:3656b0de0e43 517 P0 = ~P0;
bollenn 3:3656b0de0e43 518 }
bollenn 3:3656b0de0e43 519
bollenn 3:3656b0de0e43 520 if ((u8BYTE & (1 << 1)) != 0)
bollenn 3:3656b0de0e43 521 {
bollenn 3:3656b0de0e43 522 P0 = ~P0;
bollenn 3:3656b0de0e43 523 }
bollenn 3:3656b0de0e43 524
bollenn 3:3656b0de0e43 525 if ((u8BYTE & (1 << 2)) != 0)
bollenn 3:3656b0de0e43 526 {
bollenn 3:3656b0de0e43 527 P0 = ~P0;
bollenn 3:3656b0de0e43 528 }
bollenn 3:3656b0de0e43 529
bollenn 3:3656b0de0e43 530 if ((u8BYTE & (1 << 4)) != 0)
bollenn 3:3656b0de0e43 531 {
bollenn 3:3656b0de0e43 532 P0 = ~P0;
bollenn 3:3656b0de0e43 533 }
bollenn 3:3656b0de0e43 534
bollenn 3:3656b0de0e43 535 if ((u8BYTE & (1 << 1)) != 0)
bollenn 3:3656b0de0e43 536 {
bollenn 3:3656b0de0e43 537 P1 = ~P1;
bollenn 3:3656b0de0e43 538 }
bollenn 3:3656b0de0e43 539
bollenn 3:3656b0de0e43 540 if ((u8BYTE & (1 << 3)) != 0)
bollenn 3:3656b0de0e43 541 {
bollenn 3:3656b0de0e43 542 P1 = ~P1;
bollenn 3:3656b0de0e43 543 }
bollenn 3:3656b0de0e43 544
bollenn 3:3656b0de0e43 545 if ((u8BYTE & (1 << 4)) != 0)
bollenn 3:3656b0de0e43 546 {
bollenn 3:3656b0de0e43 547 P1 = ~P1;
bollenn 3:3656b0de0e43 548 }
bollenn 3:3656b0de0e43 549
bollenn 3:3656b0de0e43 550 if ((u8BYTE & (1 << 5)) != 0)
bollenn 3:3656b0de0e43 551 {
bollenn 3:3656b0de0e43 552 P1 = ~P1;
bollenn 3:3656b0de0e43 553 }
bollenn 3:3656b0de0e43 554
bollenn 3:3656b0de0e43 555 P1 = ~P1;
bollenn 3:3656b0de0e43 556
bollenn 3:3656b0de0e43 557 u8BYTE &= 0x3f; /* Delete MSB's */
bollenn 3:3656b0de0e43 558
bollenn 3:3656b0de0e43 559 if (P0 != 0)
bollenn 3:3656b0de0e43 560 {
bollenn 3:3656b0de0e43 561 u8BYTE |= (1 << 6);
bollenn 3:3656b0de0e43 562 }
bollenn 3:3656b0de0e43 563
bollenn 3:3656b0de0e43 564 if (P1 != 0)
bollenn 3:3656b0de0e43 565 {
bollenn 3:3656b0de0e43 566 u8BYTE |= (1 << 7);
bollenn 3:3656b0de0e43 567 }
bollenn 3:3656b0de0e43 568
bollenn 3:3656b0de0e43 569 return (u8BYTE);
bollenn 3:3656b0de0e43 570 }
bollenn 3:3656b0de0e43 571
bollenn 0:c91a9ebab739 572 /* EOF */