Nico Bollen / LIN

Dependents:   MBED_LIN_RGB_Master_Example

Committer:
bollenn
Date:
Tue Jun 16 06:22:42 2015 +0000
Revision:
4:41b153e9a39c
Parent:
3:3656b0de0e43
Child:
5:b42737f5dabc
Commit after first tests

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