Menu

Broker.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2008-2010 Michael Schulze <mschulze@ivs.cs.uni-magdeburg.de>
00004  * All rights reserved.
00005  *
00006  *    Redistribution and use in source and binary forms, with or without
00007  *    modification, are permitted provided that the following conditions
00008  *    are met:
00009  *
00010  *    * Redistributions of source code must retain the above copyright
00011  *      notice, this list of conditions and the following disclaimer.
00012  *
00013  *    * Redistributions in binary form must reproduce the above copyright
00014  *      notice, this list of conditions and the following disclaimer in
00015  *      the documentation and/or other materials provided with the
00016  *      distribution.
00017  *
00018  *    * Neither the name of the copyright holders nor the names of
00019  *      contributors may be used to endorse or promote products derived
00020  *      from this software without specific prior written permission.
00021  *
00022  *
00023  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00024  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00025  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00026  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *
00036  * $Id$
00037  *
00038  ******************************************************************************/
00039 
00040 #ifndef __ccp_Broker_h__
00041 #define __ccp_Broker_h__
00042 
00043 #include "mw/nl/can/constants.h"
00044 #include "mw/nl/can/canETAGS.h"
00045 #include "mw/common/UID.h"
00046 
00047 
00048 namespace famouso {
00049     namespace mw {
00050         namespace nl {
00051             namespace CAN {
00052                 namespace ccp {
00053                     using namespace famouso::mw::nl::CAN::detail;
00054 
00055                     //
00056                     // damit der Algorithmus ordentlich funktioniert, ist eine
00057                     // Randbedingung, dass die UID = 0x0 von keinem Knoten
00058                     // verwendet wird.
00059                     //
00060                     template < class CAN_Driver >
00061                     class Broker {
00062 
00063                             typedef typename CAN_Driver::MOB::IDType IDType;
00064 
00065                             UID knownNodes [constants::ccp::count];
00066                             uint8_t ccp_stage;
00067                             UID uid;
00068 
00069                             uint8_t search_tx_node(const UID &uid) {
00070                                 uint8_t freeplace = 0xff;
00071                                 for (uint8_t i = 0; i < constants::ccp::count; ++i) {
00072                                     if (knownNodes[i] == UID()) {
00073                                         freeplace = i;
00074                                     } else {
00075                                         if (knownNodes[i] == uid) return i;
00076                                     }
00077                                 }
00078                                 if (freeplace != 0xff)
00079                                     knownNodes[freeplace] = uid;
00080                                 return freeplace;
00081                             }
00082 
00083                             bool handle_ccp_rsi(typename CAN_Driver::MOB &mob) {
00084                                 IDType *id = &mob.id();
00085                                 // extrahiere zunaechst die wichtigsten Infos
00086                                 uint8_t nibble = id->ccp_nibble();
00087                                 uint8_t stage = id->ccp_stage();
00088                                 uint8_t tx_node = constants::Broker_tx_node;
00089 
00090                                 // kommt die Nachricht von jemandem der im richtigen stage ist?
00091                                 if (!(ccp_stage == stage)) {
00092                                     ::logging::log::emit< ::logging::Error>()
00093                                         << PROGMEMSTRING("received ccp rsi for stage ")
00094                                         << static_cast<uint32_t>(stage)
00095                                         << PROGMEMSTRING(" but I am in stage ")
00096                                         << static_cast<uint32_t>(ccp_stage)
00097                                         << PROGMEMSTRING(" dropping it.")
00098                                         << ::logging::log::endl;
00099                                         return false;
00100                                 } else {
00101                                     // stage aktualisieren
00102                                     --ccp_stage;
00103                                     // Immer den StageZaehler im letzten nibble im letzten
00104                                     // Datenbyte mitschicken. Wenn stage == 0 dann wird es
00105                                     // durch den richtigen Inhalt spaeter ueberschrieben
00106                                     uid.tab()[7] = (uid.tab()[7] & 0xF0) | stage;
00107                                     // die UID zusammenfassen
00108                                     uid.tab()[7-(stage>>1)] |= (stage & 0x1) ? (nibble << 4) : nibble;
00109                                     // 0xFD is non-real-time
00110                                     // \todo RealTimeClasses for the CAN-Bus needs to be defined somewhere
00111                                     id->prio(0xFD);
00112                                     id->etag(famouso::mw::nl::CAN::detail::ETAGS::CCP_SSI);
00113                                     mob.len(8);
00114                                     // kopieren des uid in die Nachricht um auf ClientSeite die Arbitrierung
00115                                     // durchfuehren zu koennen.
00116                                     for (uint8_t i = 0; i < 8; ++i) {
00117                                         mob.data()[i] = uid.tab()[i];
00118                                     }
00119                                     // wenn wir im letzten Stage sind, weisen wir eine KnotenID zu
00120                                     if (!stage) {
00121                                         // generiere KnotenID, kein freier darf nicht vorkommen, weil dann
00122                                         // der knoten keine tx_node bekommt
00123                                         if ((tx_node = search_tx_node(uid)) > constants::Broker_tx_node) {
00124                                             ::logging::log::emit< ::logging::Error>()
00125                                                 << PROGMEMSTRING("more than ")
00126                                                 << static_cast<short>(constants::Broker_tx_node)
00127                                                 << PROGMEMSTRING(" nodes configured that means something went wrong")
00128                                                 << ::logging::log::endl;
00129                                             return false;
00130                                         } else {
00131                                             ::logging::log::emit() << PROGMEMSTRING("CCP")
00132                                                 << ::logging::log::tab << ::logging::log::tab
00133                                                 << ::logging::log::tab << PROGMEMSTRING("-- NodeID  [");
00134                                             for (uint8_t i = 0;i < 8;++i) {
00135                                                 uint8_t c = uid.tab()[i];
00136                                                 if ((c < 32) || (c > 126)) c = 32;   // only printable characters
00137                                                 ::logging::log::emit() << c ;
00138                                             }
00139                                             ::logging::log::emit() << PROGMEMSTRING("] -> ")
00140                                                 << ::logging::log::hex
00141                                                 << PROGMEMSTRING("tx_node [")
00142                                                 << static_cast<uint16_t>(tx_node)
00143                                                 << PROGMEMSTRING("] ")
00144                                                 << uid.value()
00145                                                 << ::logging::log::endl;
00146                                         }
00147                                         ccp_stage = 15;
00148                                         uid = UID();
00149                                     }
00150                                     // tx_node ist entweder die des Brokers, wenn noch nicht stage 0 und
00151                                     // sonst die txnode des neuen Knoten
00152                                     id->tx_node(tx_node);
00153                                 }
00154                                 return true;
00155                             }
00156                         public:
00157                             Broker() : ccp_stage(15), uid() {}
00158 
00159                             bool handle_ccp_configure_request(typename CAN_Driver::MOB &mob, CAN_Driver& canDriver) {
00160                                 if (mob.id().etag() == famouso::mw::nl::CAN::detail::ETAGS::CCP_RSI) {
00161                                     if (handle_ccp_rsi(mob))
00162                                         canDriver.transmit(mob);
00163                                     return true;
00164                                 } else {
00165                                     return false;
00166                                 }
00167                             }
00168 
00169                             uint8_t ccp_configure_tx_node(const UID &uid, CAN_Driver& canDriver) {
00170                                 return search_tx_node(uid);
00171                             }
00172                     };
00173 
00174                 } /* namespace ccp */
00175             } /* namespace CAN */
00176         } /* namespace nl */
00177     } /* namespace mw */
00178 } /* namespace famouso */
00179 
00180 
00181 #endif