Menu

avrCANARY.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 __avrCANARY_h__
00041 #define __avrCANARY_h__
00042 
00043 #include <avr/io.h>
00044 #include <avr/interrupt.h>
00045 
00046 #include <stdint.h>
00047 
00048 #include "mw/nl/can/canID_LE_AVR.h"
00049 #include "case/Delegate.h"
00050 
00051 namespace device {
00052     namespace nic {
00053         namespace CAN {
00054 
00070             class avrCANARY {
00071                 public:
00072 
00077                     class MOB {
00078                         public:
00079                             typedef famouso::mw::nl::CAN::detail::ID<
00080                                         famouso::mw::nl::CAN::detail::famouso_CAN_ID_LE_CANARY
00081                                     > IDType;
00082                             IDType  _id;
00083                             uint8_t _data[8];
00084                             uint8_t _len;
00085 
00086                             void extended() { }
00087 
00088                             IDType& id() {
00089                                 return _id;
00090                             }
00091 
00092                             uint8_t& len() {
00093                                 return _len;
00094                             }
00095 
00096                             void len(uint8_t l) {
00097                                 _len = l;
00098                             }
00099 
00100                             uint8_t *data() {
00101                                 return _data;
00102                             }
00103 
00104                             void data(uint8_t *) {}
00105 
00106                             uint8_t &data(uint8_t i) {
00107                                 return _data[i];
00108                             }
00109                     };
00110 
00111                     explicit avrCANARY() {}
00112 
00118                     bool receive(MOB* mob) {
00119                         // save CANPAGE
00120                         register uint8_t temp = CANPAGE;
00121                         bool ret = false;
00122 
00123                         // select Mob0
00124                         CANPAGE = 0x00;
00125                         if ((CANSTMOB&(1 << RXOK))) {
00126                             // clear interrupt flag
00127                             CANSTMOB &= ~(1 << RXOK);
00128                             // get identifier
00129                             mob->id()[3] = CANIDT1;
00130                             mob->id()[2] = CANIDT2;
00131                             mob->id()[1] = CANIDT3;
00132                             mob->id()[0] = CANIDT4 & 0xF8;
00133 
00134                             // get length
00135                             mob->len() = CANCDMOB & 0xf;
00136                             // get data
00137                             for (uint8_t i = 0; i < mob->len(); i++)
00138                                 mob->data()[i] = CANMSG;
00139 
00140                             // reconfig mailbox
00141                             CANSTMOB = 0;
00142                             CANCDMOB = (1 << CONMOB1) | (1 << IDE);
00143                             ret = true;
00144                         }
00145                         //restore CANPAGE
00146                         CANPAGE = temp;
00147                         return ret;
00148 
00149                     }
00150 
00156                     void receive_blocking(MOB *mob) {
00157                         while (!receive(mob));
00158                     }
00159 
00164                     void transmit(MOB &mob) {
00165                         //enable MOb1, auto increment index, start with index = 0
00166                         CANPAGE = (1 << 4);
00167 
00168                         //set IDE bit, length = 8
00169                         CANCDMOB = (1 << IDE) | (mob.len() << DLC0);
00170 
00171                         CANIDT4 = mob.id()[0] & 0xF8;
00172                         CANIDT3 = mob.id()[1];
00173                         CANIDT2 = mob.id()[2];
00174                         CANIDT1 = mob.id()[3];
00175 
00176                         // put data in mailbox
00177                         for (unsigned char i = 0; i < mob.len(); i++)
00178                             CANMSG = mob.data()[i];
00179 
00180                         // enable transmission
00181                         CANCDMOB |= (1 << CONMOB0);
00182                         // wait until transmission complete
00183                         while (!(CANSTMOB & (1 << TXOK)));
00184                         // reset flag
00185                         CANSTMOB &= ~(1 << TXOK);
00186 
00187                     }
00188 
00189                     /*******************************************************************
00190                       CAN initialization:
00191                       Mailbox 0: Receive  --> interrupt
00192                       Mailbox 1: Transmit --> polling
00193                     *******************************************************************/
00194                     void init() {
00195                         // reset CAN interface
00196                         CANGCON |= (1 << SWRES);
00197 
00198                         // reset all MObs
00199                         for (unsigned char i = 0; i < 15; i++) {
00200                             CANPAGE = (i << 4); // select MOb
00201                             CANCDMOB = 0;       // disable MOb
00202                             CANSTMOB = 0;       // clear status
00203                             CANIDT1 = 0;        // clear ID
00204                             CANIDT2 = 0;
00205                             CANIDT3 = 0;
00206                             CANIDT4 = 0;
00207                             CANIDM1 = 0;        // clear mask
00208                             CANIDM2 = 0;
00209                             CANIDM3 = 0;
00210                             CANIDM4 = 0;
00211                             for (unsigned char j = 0; j < 8; j++)
00212                                 CANMSG = 0;     // clear data
00213                         }
00214 
00215                         // bit timing -> datasheet 264 (check table)
00216                         // 250Kbps 16MHz cpu-clk
00217                         CANBT1 = 0x0E;
00218                         CANBT2 = 0x04;
00219                         CANBT3 = 0x13;
00220 
00221                         // start CAN interface
00222                         CANGCON = (1 << ENASTB);
00223 
00224                         // configure MOb0
00225                         CANPAGE = (0 << 4);
00226                         /*      CANIDT1 = 0;                    //ID
00227                                 CANIDT2 = 0;
00228                                 CANIDT3 = 0;
00229                                 CANIDT4 = 0;
00230                                 CANIDM1 = 0;    // get all messages
00231                                 CANIDM2 = 0;    // 1 = check bit
00232                                 CANIDM3 = 0;    // 0 = ignore bit
00233                                 CANIDM4 = (1<<IDEMSK);
00234                         */
00235                         CANIDM4 |= (1 << IDEMSK);
00236                         CANSTMOB = 0;
00237                         // reception, ext. ID
00238                         CANCDMOB = (1 << CONMOB1) | (1 << IDE);
00239 
00240                         //interrupts
00241                         CANIE1 = 0;
00242                         // enable MOb0 interrupt
00243                         CANIE2 = (1 << 0);
00244                         CANSIT1 = 0;
00245                         CANSIT2 = 0;
00246 
00247                         // wait until module ready
00248                         while (!(CANGSTA & (1 << ENFG)));
00249                     }
00250 
00252                     void set_rx_Interrupt(famouso::util::Delegate<> f) {
00253                         rx_Interrupt = f;
00254                     }
00255 
00256 
00259                     void rx_interrupts(bool value) {
00260                         if (value)
00261                             CANGIE = (1 << ENIT) | (1 << ENRX); //enable receive interrupt
00262                         else
00263                             CANGIE = 0;
00264                     }
00265 
00268                     bool interrupts() {
00269                         return CANGIE & ((1 << ENIT) | (1 << ENRX));
00270                     }
00271 
00272                 private:
00276                     static famouso::util::Delegate<> rx_Interrupt;
00277 
00278                     friend void device::nic::CAN::fireCANARYInterrupt();
00279             };
00280 
00281             famouso::util::Delegate<> avrCANARY::rx_Interrupt;
00282 
00283             void inline fireCANARYInterrupt() {
00284                 device::nic::CAN::avrCANARY::rx_Interrupt();
00285             }
00286 
00287         } /* namespace CAN */
00288     } /* namespace nic */
00289 } /* namespace device */
00290 
00291 namespace {
00292     SIGNAL(SIG_CAN_INTERRUPT1) {
00293         device::nic::CAN::fireCANARYInterrupt();
00294     }
00295 }
00296 
00297 #endif