Nico Bollen / LIN

Dependents:   MBED_LIN_RGB_Master_Example

Committer:
bollenn
Date:
Tue May 26 08:33:46 2015 +0000
Revision:
3:3656b0de0e43
Parent:
2:6d4c7f841a5d
Child:
4:41b153e9a39c
updated to be inline with MLX16 LINmaster FW

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