Nico Bollen / LIN

Dependents:   MBED_LIN_RGB_Master_Example

Committer:
bollenn
Date:
Thu Jun 25 06:30:47 2015 +0000
Revision:
5:b42737f5dabc
Parent:
4:41b153e9a39c
Child:
8:63d341e53cce
fixed LIN read

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 3:3656b0de0e43 30
bollenn 4:41b153e9a39c 31 LinMaster::LinMaster(PinName InPin, PinName OutPin) : LinOutPin(OutPin), LinInPin(InPin), LinIntPin(InPin)
bollenn 0:c91a9ebab739 32 {
bollenn 3:3656b0de0e43 33 this->DriverState = INIT;
bollenn 3:3656b0de0e43 34 this->LastError = NoError;
bollenn 4:41b153e9a39c 35
bollenn 4:41b153e9a39c 36 this->LinOutPin.write(1);
bollenn 4:41b153e9a39c 37
bollenn 4:41b153e9a39c 38 this->LinInPin.mode(PullUp);
bollenn 4:41b153e9a39c 39
bollenn 4:41b153e9a39c 40 this->LinIntPin.disable_irq();
bollenn 4:41b153e9a39c 41
bollenn 4:41b153e9a39c 42 this->DriverState = IDLE;
bollenn 4:41b153e9a39c 43
bollenn 3:3656b0de0e43 44 (void)this->baudrate(9600);
bollenn 0:c91a9ebab739 45 }
bollenn 0:c91a9ebab739 46
bollenn 0:c91a9ebab739 47 LinMaster::~LinMaster()
bollenn 0:c91a9ebab739 48 {
bollenn 4:41b153e9a39c 49 this->LinIntPin.disable_irq();
bollenn 3:3656b0de0e43 50 this->MyTicker.detach();
bollenn 3:3656b0de0e43 51 this->MyTimer.stop();
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 4:41b153e9a39c 57
bollenn 4:41b153e9a39c 58 this->LinInPin.mode(PullUp);
bollenn 5:b42737f5dabc 59
bollenn 4:41b153e9a39c 60 this->LinIntPin.disable_irq();
bollenn 0:c91a9ebab739 61
bollenn 3:3656b0de0e43 62 this->DriverState = IDLE;
bollenn 2:6d4c7f841a5d 63
bollenn 0:c91a9ebab739 64 return ( true );
bollenn 0:c91a9ebab739 65 }
bollenn 0:c91a9ebab739 66
bollenn 3:3656b0de0e43 67 bool LinMaster::baudrate(uint16_t uBaud)
bollenn 0:c91a9ebab739 68 {
bollenn 0:c91a9ebab739 69 bool blReturn = false;
bollenn 0:c91a9ebab739 70
bollenn 0:c91a9ebab739 71 if ((uBaud > 0) && (uBaud <= 20000))
bollenn 0:c91a9ebab739 72 {
bollenn 3:3656b0de0e43 73 this->u16HalfBitPeriod = 1000000/(2*uBaud);
bollenn 0:c91a9ebab739 74 blReturn = true;
bollenn 0:c91a9ebab739 75 }
bollenn 0:c91a9ebab739 76
bollenn 0:c91a9ebab739 77 return ( blReturn );
bollenn 0:c91a9ebab739 78 }
bollenn 0:c91a9ebab739 79
bollenn 3:3656b0de0e43 80 uint16_t LinMaster::baudrate(void)
bollenn 0:c91a9ebab739 81 {
bollenn 3:3656b0de0e43 82 return ( 1000000 / (2 * this->u16HalfBitPeriod) );
bollenn 0:c91a9ebab739 83 }
bollenn 0:c91a9ebab739 84
bollenn 4:41b153e9a39c 85 bool LinMaster::send_frame(Frame_t * ptrFrame)
bollenn 0:c91a9ebab739 86 {
bollenn 2:6d4c7f841a5d 87 bool blReturn = false;
bollenn 2:6d4c7f841a5d 88
bollenn 4:41b153e9a39c 89 if ( (this->DriverState == IDLE) && (this->LinInPin.read() == 1) )
bollenn 2:6d4c7f841a5d 90 {
bollenn 3:3656b0de0e43 91 /* Clear and initialize all registers */
bollenn 5:b42737f5dabc 92 memset(this->RXbuf, 0, 11);
bollenn 3:3656b0de0e43 93
bollenn 3:3656b0de0e43 94 /* Disable half bit interrupt */
bollenn 3:3656b0de0e43 95 this->MyTicker.detach();
bollenn 2:6d4c7f841a5d 96
bollenn 4:41b153e9a39c 97 this->LinIntPin.disable_irq();
bollenn 5:b42737f5dabc 98
bollenn 4:41b153e9a39c 99 this->LinOutPin.write(1);
bollenn 2:6d4c7f841a5d 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 3:3656b0de0e43 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 3:3656b0de0e43 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 3:3656b0de0e43 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 3:3656b0de0e43 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 3:3656b0de0e43 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 3:3656b0de0e43 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 3:3656b0de0e43 153 this->RXtimeout = ((ptrFrame->DataLen + 1) * 14) * 2; /* Calculate RX timeout in half bit-times */
bollenn 3:3656b0de0e43 154 this->RXtimeoutSubCTR = 0;
bollenn 3:3656b0de0e43 155 }
bollenn 3:3656b0de0e43 156
bollenn 3:3656b0de0e43 157 /* Configure and start the half bit timer */
bollenn 3:3656b0de0e43 158 this->MyTicker.attach_us(this, &LinMaster::TickEventHndl, this->u16HalfBitPeriod);
bollenn 2:6d4c7f841a5d 159
bollenn 2:6d4c7f841a5d 160 blReturn = true;
bollenn 2:6d4c7f841a5d 161 }
bollenn 2:6d4c7f841a5d 162
bollenn 2:6d4c7f841a5d 163 return ( blReturn );
bollenn 2:6d4c7f841a5d 164 }
bollenn 2:6d4c7f841a5d 165
bollenn 5:b42737f5dabc 166 bool LinMaster::get_rx_data(Frame_t &ptrFrame)
bollenn 3:3656b0de0e43 167 {
bollenn 3:3656b0de0e43 168 uint16_t u16Crc;
bollenn 3:3656b0de0e43 169 uint8_t i;
bollenn 3:3656b0de0e43 170
bollenn 4:41b153e9a39c 171 if ( (this->DriverState != IDLE) || (this->LastError != NoError))
bollenn 3:3656b0de0e43 172 {
bollenn 3:3656b0de0e43 173 return (false);
bollenn 3:3656b0de0e43 174 }
bollenn 3:3656b0de0e43 175
bollenn 3:3656b0de0e43 176 /* Copy data and check RX frame CRC */
bollenn 5:b42737f5dabc 177 if (ptrFrame.CrcType == Enhanced)
bollenn 3:3656b0de0e43 178 {
bollenn 3:3656b0de0e43 179 u16Crc = RXbuf[1];
bollenn 3:3656b0de0e43 180 }
bollenn 3:3656b0de0e43 181 else
bollenn 3:3656b0de0e43 182 {
bollenn 3:3656b0de0e43 183 u16Crc = 0;
bollenn 3:3656b0de0e43 184 }
bollenn 3:3656b0de0e43 185
bollenn 5:b42737f5dabc 186 for (i = 0; i < ptrFrame.DataLen; i++)
bollenn 3:3656b0de0e43 187 {
bollenn 5:b42737f5dabc 188 ptrFrame.Data[i] = RXbuf[1 + 1 + i];
bollenn 3:3656b0de0e43 189 u16Crc += RXbuf[1 + 1 + i];
bollenn 3:3656b0de0e43 190 if (u16Crc >= 256)
bollenn 3:3656b0de0e43 191 {
bollenn 3:3656b0de0e43 192 u16Crc -= 255;
bollenn 3:3656b0de0e43 193 }
bollenn 3:3656b0de0e43 194 }
bollenn 3:3656b0de0e43 195
bollenn 5:b42737f5dabc 196 if (this->RXbuf[ptrFrame.DataLen + 2] == (uint8_t)(~u16Crc))
bollenn 3:3656b0de0e43 197 {
bollenn 3:3656b0de0e43 198 return (true);
bollenn 3:3656b0de0e43 199 }
bollenn 3:3656b0de0e43 200 else
bollenn 3:3656b0de0e43 201 {
bollenn 3:3656b0de0e43 202 return (false);
bollenn 3:3656b0de0e43 203 }
bollenn 3:3656b0de0e43 204 }
bollenn 3:3656b0de0e43 205
bollenn 2:6d4c7f841a5d 206 void LinMaster::TickEventHndl(void)
bollenn 2:6d4c7f841a5d 207 {
bollenn 3:3656b0de0e43 208 if (this->FrameStatus < Break_OK)
bollenn 2:6d4c7f841a5d 209 {
bollenn 3:3656b0de0e43 210 /* Do break field transmission */
bollenn 3:3656b0de0e43 211 if (this->breakLength > 2)
bollenn 3:3656b0de0e43 212 {
bollenn 3:3656b0de0e43 213 /* Dominant Level */
bollenn 4:41b153e9a39c 214 this->LinOutPin.write(0);
bollenn 3:3656b0de0e43 215 }
bollenn 3:3656b0de0e43 216 else
bollenn 3:3656b0de0e43 217 {
bollenn 3:3656b0de0e43 218 /* Recessive Level */
bollenn 4:41b153e9a39c 219 this->LinOutPin.write(1);
bollenn 3:3656b0de0e43 220 }
bollenn 3:3656b0de0e43 221
bollenn 3:3656b0de0e43 222 if (this->breakLength > 0)
bollenn 3:3656b0de0e43 223 {
bollenn 3:3656b0de0e43 224 this->breakLength--;
bollenn 3:3656b0de0e43 225 }
bollenn 3:3656b0de0e43 226 else
bollenn 3:3656b0de0e43 227 {
bollenn 3:3656b0de0e43 228 this->FrameStatus = Break_OK;
bollenn 3:3656b0de0e43 229 }
bollenn 2:6d4c7f841a5d 230 }
bollenn 2:6d4c7f841a5d 231 else
bollenn 2:6d4c7f841a5d 232 {
bollenn 3:3656b0de0e43 233 /* Break field was transmitted */
bollenn 3:3656b0de0e43 234 if (this->FrameLength == 0)
bollenn 2:6d4c7f841a5d 235 {
bollenn 3:3656b0de0e43 236 /* No data needs to be transmitted */
bollenn 3:3656b0de0e43 237
bollenn 3:3656b0de0e43 238 /* Disable half bit interrupt */
bollenn 3:3656b0de0e43 239 this->MyTicker.detach();
bollenn 3:3656b0de0e43 240
bollenn 3:3656b0de0e43 241 /* Disable LIN bus level interrupt */
bollenn 4:41b153e9a39c 242 this->LinIntPin.disable_irq();
bollenn 2:6d4c7f841a5d 243 }
bollenn 3:3656b0de0e43 244 else
bollenn 2:6d4c7f841a5d 245 {
bollenn 3:3656b0de0e43 246 /* Data needs to be transmitted or received */
bollenn 3:3656b0de0e43 247 if ( (this->linMessageType == S2M) &&
bollenn 3:3656b0de0e43 248 (this->FrameStatus >= ID_OK))
bollenn 2:6d4c7f841a5d 249 {
bollenn 3:3656b0de0e43 250 if (this->ByteStatus > BStart)
bollenn 3:3656b0de0e43 251 {
bollenn 3:3656b0de0e43 252 /* Not waiting for start bit */
bollenn 3:3656b0de0e43 253 this->ByteStatus = static_cast<ByteStatus_t>(static_cast<int>(this->ByteStatus)+1);
bollenn 3:3656b0de0e43 254 }
bollenn 3:3656b0de0e43 255
bollenn 3:3656b0de0e43 256 if (this->RXtimeout > 0)
bollenn 3:3656b0de0e43 257 {
bollenn 3:3656b0de0e43 258 this->RXtimeout--;
bollenn 3:3656b0de0e43 259 }
bollenn 3:3656b0de0e43 260 else
bollenn 3:3656b0de0e43 261 {
bollenn 3:3656b0de0e43 262 this->DriverState = IDLE;
bollenn 3:3656b0de0e43 263 this->LastError = NoSlaveResp;
bollenn 3:3656b0de0e43 264
bollenn 3:3656b0de0e43 265 /* Disable half bit interrupt */
bollenn 3:3656b0de0e43 266 this->MyTicker.detach();
bollenn 3:3656b0de0e43 267
bollenn 3:3656b0de0e43 268 /* Disable LIN bus level interrupt */
bollenn 4:41b153e9a39c 269 this->LinIntPin.disable_irq();
bollenn 3:3656b0de0e43 270 }
bollenn 3:3656b0de0e43 271
bollenn 3:3656b0de0e43 272 /* S2M message data receiving */
bollenn 3:3656b0de0e43 273 switch (this->ByteStatus)
bollenn 3:3656b0de0e43 274 {
bollenn 3:3656b0de0e43 275 case StartbitSample:
bollenn 3:3656b0de0e43 276 if (LinInPin.read() == 0)
bollenn 3:3656b0de0e43 277 {
bollenn 3:3656b0de0e43 278 /* OK */
bollenn 3:3656b0de0e43 279 }
bollenn 3:3656b0de0e43 280 else
bollenn 3:3656b0de0e43 281 {
bollenn 3:3656b0de0e43 282 /* TODO error */
bollenn 3:3656b0de0e43 283 }
bollenn 3:3656b0de0e43 284
bollenn 3:3656b0de0e43 285 break;
bollenn 3:3656b0de0e43 286
bollenn 3:3656b0de0e43 287 case Databit0Sample:
bollenn 3:3656b0de0e43 288 case Databit1Sample:
bollenn 3:3656b0de0e43 289 case Databit2Sample:
bollenn 3:3656b0de0e43 290 case Databit3Sample:
bollenn 3:3656b0de0e43 291 case Databit4Sample:
bollenn 3:3656b0de0e43 292 case Databit5Sample:
bollenn 3:3656b0de0e43 293 case Databit6Sample:
bollenn 3:3656b0de0e43 294 case Databit7Sample:
bollenn 3:3656b0de0e43 295 /* Mid of single bit time, do sampling */
bollenn 3:3656b0de0e43 296 this->RXbuf[RXbufIndex] >>= 1;
bollenn 3:3656b0de0e43 297 this->RXbuf[RXbufIndex] |= (LinInPin.read() << 7);
bollenn 3:3656b0de0e43 298 break;
bollenn 3:3656b0de0e43 299
bollenn 3:3656b0de0e43 300 case StopbitSample:
bollenn 3:3656b0de0e43 301 /* End of stop bit, stop Timer IRQ */
bollenn 3:3656b0de0e43 302 this->RXbufIndex++;
bollenn 3:3656b0de0e43 303 this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
bollenn 3:3656b0de0e43 304 this->ByteStatus = BStart;
bollenn 3:3656b0de0e43 305
bollenn 3:3656b0de0e43 306 /* Check the current bus level */
bollenn 4:41b153e9a39c 307 if (this->LinInPin.read() == 0)
bollenn 3:3656b0de0e43 308 {
bollenn 3:3656b0de0e43 309 this->LastError = FramingErr; /* stop bit not valid => framing error */
bollenn 3:3656b0de0e43 310 }
bollenn 3:3656b0de0e43 311
bollenn 3:3656b0de0e43 312 if ((this->RXbufIndex >= this->FrameLength) ||
bollenn 3:3656b0de0e43 313 (this->LastError != NoError))
bollenn 3:3656b0de0e43 314 {
bollenn 3:3656b0de0e43 315 /* All requested data bytes are received or an error occurred */
bollenn 3:3656b0de0e43 316 this->DriverState = IDLE;
bollenn 3:3656b0de0e43 317
bollenn 3:3656b0de0e43 318 /* Disable half bit interrupt */
bollenn 3:3656b0de0e43 319 this->MyTicker.detach();
bollenn 3:3656b0de0e43 320
bollenn 3:3656b0de0e43 321 /* Disable LIN bus level interrupt */
bollenn 4:41b153e9a39c 322 this->LinIntPin.disable_irq();
bollenn 3:3656b0de0e43 323 }
bollenn 3:3656b0de0e43 324 else
bollenn 3:3656b0de0e43 325 {
bollenn 3:3656b0de0e43 326 /* Wait for a new data byte */
bollenn 5:b42737f5dabc 327 this->MyTimer.start();
bollenn 3:3656b0de0e43 328
bollenn 3:3656b0de0e43 329 /* Disable LIN bus level interrupt */
bollenn 5:b42737f5dabc 330 this->LinIntPin.fall(this, &LinMaster::PinEventHndl);
bollenn 4:41b153e9a39c 331 this->LinIntPin.enable_irq();
bollenn 3:3656b0de0e43 332 }
bollenn 3:3656b0de0e43 333
bollenn 3:3656b0de0e43 334 break;
bollenn 5:b42737f5dabc 335
bollenn 3:3656b0de0e43 336 case Databit0Edge:
bollenn 3:3656b0de0e43 337 case Databit1Edge:
bollenn 3:3656b0de0e43 338 case Databit2Edge:
bollenn 3:3656b0de0e43 339 case Databit3Edge:
bollenn 3:3656b0de0e43 340 case Databit4Edge:
bollenn 3:3656b0de0e43 341 case Databit5Edge:
bollenn 3:3656b0de0e43 342 case Databit6Edge:
bollenn 3:3656b0de0e43 343 case Databit7Edge:
bollenn 3:3656b0de0e43 344 case StopbitEdge:
bollenn 3:3656b0de0e43 345 case BDone:
bollenn 3:3656b0de0e43 346 case BStart:
bollenn 3:3656b0de0e43 347 default:
bollenn 3:3656b0de0e43 348 /* Do nothing */
bollenn 3:3656b0de0e43 349 break;
bollenn 3:3656b0de0e43 350 }
bollenn 2:6d4c7f841a5d 351 }
bollenn 2:6d4c7f841a5d 352 else
bollenn 2:6d4c7f841a5d 353 {
bollenn 3:3656b0de0e43 354 /* Transmission of Sync + Frame ID and M2S frame data */
bollenn 3:3656b0de0e43 355 this->ByteStatus = static_cast<ByteStatus_t>(static_cast<int>(this->ByteStatus)+1);
bollenn 3:3656b0de0e43 356
bollenn 3:3656b0de0e43 357 switch (this->ByteStatus)
bollenn 3:3656b0de0e43 358 {
bollenn 3:3656b0de0e43 359 case StartbitEdge:
bollenn 3:3656b0de0e43 360 /* Start bit : start */
bollenn 4:41b153e9a39c 361 this->LinOutPin.write(0);
bollenn 3:3656b0de0e43 362 break;
bollenn 3:3656b0de0e43 363
bollenn 3:3656b0de0e43 364 case StartbitSample:
bollenn 3:3656b0de0e43 365 /* Start bit : mid */
bollenn 3:3656b0de0e43 366 break;
bollenn 3:3656b0de0e43 367
bollenn 3:3656b0de0e43 368 case Databit0Edge:
bollenn 3:3656b0de0e43 369 case Databit1Edge:
bollenn 3:3656b0de0e43 370 case Databit2Edge:
bollenn 3:3656b0de0e43 371 case Databit3Edge:
bollenn 3:3656b0de0e43 372 case Databit4Edge:
bollenn 3:3656b0de0e43 373 case Databit5Edge:
bollenn 3:3656b0de0e43 374 case Databit6Edge:
bollenn 3:3656b0de0e43 375 case Databit7Edge:
bollenn 3:3656b0de0e43 376 /* Start of new bit time */
bollenn 3:3656b0de0e43 377 if (this->TXbuf[this->TXbufIndex] & 0x01)
bollenn 3:3656b0de0e43 378 {
bollenn 3:3656b0de0e43 379 /* Recessive Level */
bollenn 4:41b153e9a39c 380 this->LinOutPin.write(1);
bollenn 3:3656b0de0e43 381 }
bollenn 3:3656b0de0e43 382 else
bollenn 3:3656b0de0e43 383 {
bollenn 3:3656b0de0e43 384 /* Dominant Level */
bollenn 4:41b153e9a39c 385 this->LinOutPin.write(0);
bollenn 3:3656b0de0e43 386 }
bollenn 3:3656b0de0e43 387
bollenn 3:3656b0de0e43 388 this->TXbuf[this->TXbufIndex] >>= 1;
bollenn 3:3656b0de0e43 389 break;
bollenn 3:3656b0de0e43 390
bollenn 3:3656b0de0e43 391 case Databit0Sample:
bollenn 3:3656b0de0e43 392 case Databit1Sample:
bollenn 3:3656b0de0e43 393 case Databit2Sample:
bollenn 3:3656b0de0e43 394 case Databit3Sample:
bollenn 3:3656b0de0e43 395 case Databit4Sample:
bollenn 3:3656b0de0e43 396 case Databit5Sample:
bollenn 3:3656b0de0e43 397 case Databit6Sample:
bollenn 3:3656b0de0e43 398 case Databit7Sample:
bollenn 3:3656b0de0e43 399 /* Odd overflow, mid of bit time ==> sample the bus for RX */
bollenn 3:3656b0de0e43 400 this->RXbuf[this->RXbufIndex] >>= 1;
bollenn 5:b42737f5dabc 401 this->RXbuf[this->RXbufIndex] |= ((LinInPin.read() << 7) & 0x80);
bollenn 3:3656b0de0e43 402 break;
bollenn 3:3656b0de0e43 403
bollenn 3:3656b0de0e43 404 case StopbitEdge:
bollenn 3:3656b0de0e43 405 /* Stop bit : start */
bollenn 4:41b153e9a39c 406 this->LinOutPin.write(1);
bollenn 3:3656b0de0e43 407 break;
bollenn 2:6d4c7f841a5d 408
bollenn 3:3656b0de0e43 409 case StopbitSample:
bollenn 3:3656b0de0e43 410 /* Stop bit : mid / level check */
bollenn 4:41b153e9a39c 411 if (this->LinInPin.read() == 0)
bollenn 3:3656b0de0e43 412 {
bollenn 3:3656b0de0e43 413 /* Stop bit not valid => framing error */
bollenn 3:3656b0de0e43 414 this->LastError = FramingErr;
bollenn 3:3656b0de0e43 415 this->DriverState = IDLE;
bollenn 3:3656b0de0e43 416
bollenn 3:3656b0de0e43 417 /* Disable half bit interrupt */
bollenn 3:3656b0de0e43 418 this->MyTicker.detach();
bollenn 3:3656b0de0e43 419
bollenn 3:3656b0de0e43 420 /* Disable LIN bus level interrupt */
bollenn 4:41b153e9a39c 421 this->LinIntPin.disable_irq();
bollenn 3:3656b0de0e43 422 }
bollenn 3:3656b0de0e43 423
bollenn 3:3656b0de0e43 424 break;
bollenn 3:3656b0de0e43 425
bollenn 3:3656b0de0e43 426 case BDone:
bollenn 3:3656b0de0e43 427 /* Stop bit : finished */
bollenn 3:3656b0de0e43 428 this->ByteStatus = BStart;
bollenn 3:3656b0de0e43 429 this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
bollenn 3:3656b0de0e43 430 this->TXbufIndex++;
bollenn 3:3656b0de0e43 431 this->RXbufIndex++;
bollenn 3:3656b0de0e43 432
bollenn 3:3656b0de0e43 433 if (this->linMessageType == S2M)
bollenn 3:3656b0de0e43 434 {
bollenn 3:3656b0de0e43 435 /* S2M frame */
bollenn 3:3656b0de0e43 436 if (this->FrameStatus == ID_OK)
bollenn 3:3656b0de0e43 437 {
bollenn 3:3656b0de0e43 438 /* Stop bit of header is sent, now start receiving data bytes */
bollenn 3:3656b0de0e43 439 this->MyTimer.start();
bollenn 5:b42737f5dabc 440
bollenn 5:b42737f5dabc 441 /* Enable LIN bus level interrupt */
bollenn 5:b42737f5dabc 442 this->LinIntPin.fall(this, &LinMaster::PinEventHndl);
bollenn 4:41b153e9a39c 443 this->LinIntPin.enable_irq();
bollenn 3:3656b0de0e43 444 }
bollenn 3:3656b0de0e43 445 }
bollenn 3:3656b0de0e43 446 else if (this->TXbufIndex >= this->FrameLength)
bollenn 3:3656b0de0e43 447 {
bollenn 3:3656b0de0e43 448 /* M2S frame, Last byte is sent */
bollenn 3:3656b0de0e43 449 this->LastError = NoError;
bollenn 3:3656b0de0e43 450 this->DriverState = IDLE;
bollenn 3:3656b0de0e43 451
bollenn 3:3656b0de0e43 452 /* Disable half bit interrupt */
bollenn 3:3656b0de0e43 453 this->MyTicker.detach();
bollenn 3:3656b0de0e43 454
bollenn 3:3656b0de0e43 455 /* Disable LIN bus level interrupt */
bollenn 4:41b153e9a39c 456 this->LinIntPin.disable_irq();
bollenn 3:3656b0de0e43 457 }
bollenn 3:3656b0de0e43 458
bollenn 3:3656b0de0e43 459 break;
bollenn 3:3656b0de0e43 460
bollenn 3:3656b0de0e43 461 default:
bollenn 3:3656b0de0e43 462 break;
bollenn 3:3656b0de0e43 463 }
bollenn 2:6d4c7f841a5d 464 }
bollenn 2:6d4c7f841a5d 465 }
bollenn 2:6d4c7f841a5d 466 }
bollenn 0:c91a9ebab739 467 }
bollenn 0:c91a9ebab739 468
bollenn 3:3656b0de0e43 469 void LinMaster::PinEventHndl(void)
bollenn 3:3656b0de0e43 470 {
bollenn 3:3656b0de0e43 471 switch (this->DriverState)
bollenn 3:3656b0de0e43 472 {
bollenn 3:3656b0de0e43 473 case TRANSMIT:
bollenn 3:3656b0de0e43 474 case RECEIVE:
bollenn 3:3656b0de0e43 475 {
bollenn 3:3656b0de0e43 476 this->ByteStatus = StartbitEdge; /* Set status of the received byte */
bollenn 3:3656b0de0e43 477 this->RXtimeoutSubCTR += this->MyTimer.read_us();
bollenn 3:3656b0de0e43 478 this->MyTimer.stop();
bollenn 3:3656b0de0e43 479
bollenn 3:3656b0de0e43 480 /* Reset ticker */
bollenn 3:3656b0de0e43 481 this->MyTicker.detach();
bollenn 3:3656b0de0e43 482 this->MyTicker.attach_us(this, &LinMaster::TickEventHndl, this->u16HalfBitPeriod);
bollenn 3:3656b0de0e43 483
bollenn 3:3656b0de0e43 484 /* Disable LIN bus level interrupt */
bollenn 4:41b153e9a39c 485 this->LinIntPin.disable_irq();
bollenn 3:3656b0de0e43 486
bollenn 3:3656b0de0e43 487 if (this->RXtimeoutSubCTR > this->u16HalfBitPeriod)
bollenn 3:3656b0de0e43 488 {
bollenn 3:3656b0de0e43 489 this->RXtimeoutSubCTR -= this->u16HalfBitPeriod;
bollenn 3:3656b0de0e43 490 if (this->RXtimeout > 0)
bollenn 3:3656b0de0e43 491 {
bollenn 3:3656b0de0e43 492 this->RXtimeout--;
bollenn 3:3656b0de0e43 493 }
bollenn 3:3656b0de0e43 494 }
bollenn 3:3656b0de0e43 495
bollenn 3:3656b0de0e43 496 break;
bollenn 3:3656b0de0e43 497 }
bollenn 3:3656b0de0e43 498
bollenn 3:3656b0de0e43 499 case IDLE:
bollenn 3:3656b0de0e43 500 case DOMINANT:
bollenn 3:3656b0de0e43 501 case TXWAKEUP:
bollenn 3:3656b0de0e43 502 break;
bollenn 3:3656b0de0e43 503
bollenn 3:3656b0de0e43 504 case RXWAKEUP:
bollenn 3:3656b0de0e43 505 default:
bollenn 3:3656b0de0e43 506 this->DriverState = RXWAKEUP; /* It's a wake up pulse */
bollenn 3:3656b0de0e43 507 break;
bollenn 3:3656b0de0e43 508 }
bollenn 3:3656b0de0e43 509 }
bollenn 3:3656b0de0e43 510
bollenn 3:3656b0de0e43 511 /** Calculate the parity bits
bollenn 3:3656b0de0e43 512 *
bollenn 3:3656b0de0e43 513 * @param u8BYTE original byte
bollenn 3:3656b0de0e43 514 * @return BYTE including parity bits
bollenn 3:3656b0de0e43 515 */
bollenn 3:3656b0de0e43 516 uint8_t LinMaster::parity(uint8_t u8BYTE)
bollenn 3:3656b0de0e43 517 {
bollenn 3:3656b0de0e43 518 uint8_t P0 = 0;
bollenn 3:3656b0de0e43 519 uint8_t P1 = 0;
bollenn 3:3656b0de0e43 520
bollenn 3:3656b0de0e43 521 /* P0 = ID0 + ID1 + ID2 + ID4
bollenn 3:3656b0de0e43 522 * P1 = ~(ID1 + ID3 + ID4 + ID5)
bollenn 3:3656b0de0e43 523 */
bollenn 3:3656b0de0e43 524 if ((u8BYTE & (1 << 0)) != 0)
bollenn 3:3656b0de0e43 525 {
bollenn 3:3656b0de0e43 526 P0 = ~P0;
bollenn 3:3656b0de0e43 527 }
bollenn 3:3656b0de0e43 528
bollenn 3:3656b0de0e43 529 if ((u8BYTE & (1 << 1)) != 0)
bollenn 3:3656b0de0e43 530 {
bollenn 3:3656b0de0e43 531 P0 = ~P0;
bollenn 3:3656b0de0e43 532 }
bollenn 3:3656b0de0e43 533
bollenn 3:3656b0de0e43 534 if ((u8BYTE & (1 << 2)) != 0)
bollenn 3:3656b0de0e43 535 {
bollenn 3:3656b0de0e43 536 P0 = ~P0;
bollenn 3:3656b0de0e43 537 }
bollenn 3:3656b0de0e43 538
bollenn 3:3656b0de0e43 539 if ((u8BYTE & (1 << 4)) != 0)
bollenn 3:3656b0de0e43 540 {
bollenn 3:3656b0de0e43 541 P0 = ~P0;
bollenn 3:3656b0de0e43 542 }
bollenn 3:3656b0de0e43 543
bollenn 3:3656b0de0e43 544 if ((u8BYTE & (1 << 1)) != 0)
bollenn 3:3656b0de0e43 545 {
bollenn 3:3656b0de0e43 546 P1 = ~P1;
bollenn 3:3656b0de0e43 547 }
bollenn 3:3656b0de0e43 548
bollenn 3:3656b0de0e43 549 if ((u8BYTE & (1 << 3)) != 0)
bollenn 3:3656b0de0e43 550 {
bollenn 3:3656b0de0e43 551 P1 = ~P1;
bollenn 3:3656b0de0e43 552 }
bollenn 3:3656b0de0e43 553
bollenn 3:3656b0de0e43 554 if ((u8BYTE & (1 << 4)) != 0)
bollenn 3:3656b0de0e43 555 {
bollenn 3:3656b0de0e43 556 P1 = ~P1;
bollenn 3:3656b0de0e43 557 }
bollenn 3:3656b0de0e43 558
bollenn 3:3656b0de0e43 559 if ((u8BYTE & (1 << 5)) != 0)
bollenn 3:3656b0de0e43 560 {
bollenn 3:3656b0de0e43 561 P1 = ~P1;
bollenn 3:3656b0de0e43 562 }
bollenn 3:3656b0de0e43 563
bollenn 3:3656b0de0e43 564 P1 = ~P1;
bollenn 3:3656b0de0e43 565
bollenn 3:3656b0de0e43 566 u8BYTE &= 0x3f; /* Delete MSB's */
bollenn 3:3656b0de0e43 567
bollenn 3:3656b0de0e43 568 if (P0 != 0)
bollenn 3:3656b0de0e43 569 {
bollenn 3:3656b0de0e43 570 u8BYTE |= (1 << 6);
bollenn 3:3656b0de0e43 571 }
bollenn 3:3656b0de0e43 572
bollenn 3:3656b0de0e43 573 if (P1 != 0)
bollenn 3:3656b0de0e43 574 {
bollenn 3:3656b0de0e43 575 u8BYTE |= (1 << 7);
bollenn 3:3656b0de0e43 576 }
bollenn 3:3656b0de0e43 577
bollenn 3:3656b0de0e43 578 return (u8BYTE);
bollenn 3:3656b0de0e43 579 }
bollenn 3:3656b0de0e43 580
bollenn 0:c91a9ebab739 581 /* EOF */