CANPort provides a higher level interface to a CAN communication channel, and provides timestamping, servicing additional hardware interfaces (optional activity LED, CAN transceiver slope control)
Diff: CANPort.cpp
- Revision:
- 0:7b81b19d9b10
- Child:
- 1:f0b4e47d948d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CANPort.cpp Sun Jul 15 15:15:19 2012 +0000 @@ -0,0 +1,243 @@ +/// @file CANPort.cpp is where all the port level functionality resides +/// +/// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved. +/// Individuals may use this application for evaluation or non-commercial +/// purposes. Within this restriction, changes may be made to this application +/// as long as this copyright notice is retained. The user shall make +/// clear that their work is a derived work, and not the original. +/// Users of this application and sources accept this application "as is" and +/// shall hold harmless Smartware Computing, for any undesired results while +/// using this application - whether real or imagined. +/// +/// @author David Smart, Smartware Computing +/// +/// 20110718 +/// Fixed a bug in the Receive handler - it was not propagating the message +/// out. +/// 20110605 +/// Revised the SlopeControl so that it actually works for any change in value +/// where it was previously able to go low or high, but once as an input it +/// then would not go back to an output. +/// +#include "mbed.h" +#include "CANPort.h" +#include "Utilities.h" + +#define FLASH_PERIOD (float)0.04 +#define FLASH_TX_LEVEL 0.10 +#define FLASH_RX_LEVEL 1.00 + + +CANPort::CANPort(CANCHANNEL_T chNum, PinName rd, PinName td, PinName _activityPin, PinName _slopePin, CANSlopeControl_T slope) { + channel = chNum; + can = new CAN(rd, td); + if (_activityPin != NC) { + activityPin = new PwmOut(_activityPin); + activityPin->pulsewidth_us(100); + } + else + activityPin = NULL; + if (_slopePin != NC) { + slopePin = new DigitalInOut(_slopePin); + SetSlopeControl(slope); + } else + slopePin = NULL; + slopePinName = _slopePin; + txCounter = 0; + rxCounter = 0; +} + + +CANPort::~CANPort() { + if (slopePin) + delete slopePin; + if (activityPin) + delete activityPin; + if (can) + delete can; + slopePin = NULL; + activityPin = NULL; + can = NULL; +} + + +bool CANPort::TransmitMsg(CANmsg msg) { + bool success = false; + + if (msg.dir == xmt) { // we have to have indicated our intent to transmit + msg.ch = channel; + if (can->write(CANMessage(msg.id, (char *)&msg.data, msg.len, CANData, msg.format))) { + txCounter++; + Flash(msg.dir); + success = true; + } + } + return success; +} + + +bool CANPort::ReceiveMsg(CANmsg &msg) { + bool success = false; + CANMessage _msg; + + if (can->read(_msg)) { + /// @TODO This looks like a very inefficient method, but it works. + CANmsg Xmsg(channel, rcv, _msg); + msg = Xmsg; + rxCounter++; + Flash(msg.dir); + success = true; + } + return success; +} + + +void CANPort::Attach( void (*fptr)(void)) { + can->attach(fptr); +} + + +void CANPort::Extinguish(void) { + if (activityPin) { + *activityPin = 0.0; + } +} + + +void CANPort::Flash(CANDIR_T tx) { + if (activityPin) { + *activityPin = (tx == xmt) ? FLASH_TX_LEVEL : FLASH_RX_LEVEL; // dim for transmit, bright for receive + activityTimeout.attach(this, &CANPort::Extinguish, FLASH_PERIOD); + } +} + + +bool CANPort::SetAutoReset(bool enable) { + autoReset = enable; + return true; +} + + +bool CANPort::SetBusMode(CANBusMode_T mode) { + switch (mode) { + case MONITOR: + can->monitor(true); + busMode = mode; + break; + case ACTIVE: + can->monitor(false); + busMode = mode; + break; + default: + return false; + } + return true; +} + + +CANBusMode_T CANPort::GetBusMode() { + return busMode; +} + + +bool CANPort::SetSlopeControl(CANSlopeControl_T slope) { + if (slopePin) { + slopeMode = slope; + switch (slope) { + case HIGHSPEED: + slopePin->output(); + slopePin->write(0); + break; + case NORMALSPEED: + slopePin->input(); + slopePin->mode(PullNone); + break; + case STANDBY: + slopePin->output(); + slopePin->write(1); + break; + default: + return false; + } + return true; + } else + return false; +} + + +CANSlopeControl_T CANPort::GetSlopeControl() { + return slopeMode; +} + + +bool CANPort::SetBitRate(int rate) { + if (can->frequency(rate)) { + bitRate = rate; + return true; + } else { + return false; + } +} + + +int CANPort::GetBitRate() { + return bitRate; +} + + +int CANPort::GetTxCounter() { + return txCounter; +} + + +int CANPort::GetRxCounter() { + return rxCounter; +} + + +int CANPort::GetTxErrorCounter() { + return can->tderror(); +} + + +int CANPort::GetRxErrorCounter() { + return can->rderror(); +} + + +bool CANPort::ResetChip() { + can->reset(); + return true; +} + + +void CANPort::PrintInfo(Serial * stream) { + if (stream) { + stream->printf("\r\n"); + stream->printf(" Register: CAN1 CAN2 Register: CAN1 CAN2\r\n"); + stream->printf(" MOD: %08X %08X ", LPC_CAN1->MOD, LPC_CAN2->MOD); + stream->printf(" GSR: %08X %08X\r\n", LPC_CAN1->GSR, LPC_CAN2->GSR); + stream->printf(" ICR: %08X %08X ", LPC_CAN1->ICR, LPC_CAN2->ICR); + stream->printf(" IER: %08X %08X\r\n", LPC_CAN1->IER, LPC_CAN2->IER); + stream->printf(" BTR: %08X %08X ", LPC_CAN1->BTR, LPC_CAN2->BTR); + stream->printf(" EWL: %08X %08X\r\n", LPC_CAN1->EWL, LPC_CAN2->EWL); + stream->printf(" SR: %08X %08X ", LPC_CAN1->SR, LPC_CAN2->SR ); + stream->printf(" RFS: %08X %08X\r\n", LPC_CAN1->RFS, LPC_CAN2->RFS); + stream->printf(" RID: %08X %08X ", LPC_CAN1->RID, LPC_CAN2->RID); + stream->printf(" RDA: %08X %08X\r\n", LPC_CAN1->RDA, LPC_CAN2->RDA); + stream->printf(" RDB: %08X %08X ", LPC_CAN1->RDB, LPC_CAN2->RDB); + stream->printf(" TFI1: %08X %08X\r\n", LPC_CAN1->TFI1, LPC_CAN2->TFI1); + stream->printf(" TID1: %08X %08X ", LPC_CAN1->TID1, LPC_CAN2->TID1); + stream->printf(" TDA1: %08X %08X\r\n", LPC_CAN1->TDA1, LPC_CAN2->TDA1); + stream->printf(" TDB1: %08X %08X ", LPC_CAN1->TDB1, LPC_CAN2->TDB1); + stream->printf(" TFI2: %08X %08X\r\n", LPC_CAN1->TFI2, LPC_CAN2->TFI2); + stream->printf(" TID2: %08X %08X ", LPC_CAN1->TID2, LPC_CAN2->TID2); + stream->printf(" TDA2: %08X %08X\r\n", LPC_CAN1->TDA2, LPC_CAN2->TDA2); + stream->printf(" TDB2: %08X %08X ", LPC_CAN1->TDB2, LPC_CAN2->TDB2); + stream->printf(" TFI3: %08X %08X\r\n", LPC_CAN1->TFI3, LPC_CAN2->TFI3); + stream->printf(" TID3: %08X %08X ", LPC_CAN1->TID3, LPC_CAN2->TID3); + stream->printf(" TDA3: %08X %08X\r\n", LPC_CAN1->TDA3, LPC_CAN2->TDA3); + stream->printf(" TDB3: %08X %08X ", LPC_CAN1->TDB3, LPC_CAN2->TDB3); + stream->printf("\r\n"); + } +}