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)
CANPort.cpp
- Committer:
- WiredHome
- Date:
- 2012-07-15
- Revision:
- 0:7b81b19d9b10
- Child:
- 1:f0b4e47d948d
File content as of revision 0:7b81b19d9b10:
/// @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"); } }