Subversion Repositories HomeAutomation

Rev

Rev 363 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*********************************************************************
  2.  *
  3.  *                  CAN module
  4.  *
  5.  *********************************************************************
  6.  * FileName:        $HeadURL: https://svn.auml.se/svn/HomeAutomation/branches/modules/EmbeddedSoftware/PIC/canBase/Source/CAN.c $
  7.  * Last changed:    $LastChangedDate: 2007-03-13 18:29:20 +0100 (Tue, 13 Mar 2007) $
  8.  * By:              $LastChangedBy: johboh $
  9.  * Revision:        $Revision: 363 $
  10.  ********************************************************************/
  11.  
  12. #include <CANdefs.h>
  13. #include <stackTasks.h>
  14. #include <CAN.h>
  15. #include <EEaccess.h>
  16. #include <funcdefs.h>
  17. #include <Tick.h>
  18.  
  19. static TICK heartbeat;
  20. static int MY_ID = DEFAULT_ID;
  21. static CAN_PACKET outCp;
  22.  
  23. static void canGetPacket(void);
  24.  
  25. BYTE myId() { return MY_ID; }
  26.  
  27.  
  28. /*
  29. *   Function: canInit
  30. *
  31. *   Input:  none
  32. *   Output: none
  33. *   Pre-conditions: none
  34. *   Affects: Changes can registers.
  35. *   Depends: none.
  36. */
  37. void canInit()
  38. {
  39.     CANCON = 0x80; //request config mode
  40.     while ((CANSTAT & 0xE0) != 0x80 ); //wait for config mode request
  41.  
  42.     // BAUD AND TQS
  43.  
  44.     // 500Khz@40Mhz (new by the book)
  45.     BRGCON1 = 0x04;
  46.     BRGCON2 = 0xD1;
  47.     BRGCON3 = 0x81;
  48.  
  49.     //BRGCON1=0;
  50.    
  51.     // Sync_Seq = 2 x TQ = 1
  52.     //BRGCON1bits.SJW1=0;
  53.     //BRGCON1bits.SJW0=1;
  54.    
  55.     // Setting BRP.
  56.     //BRGCON1=BRGCON1|CAN_BRP;
  57.    
  58.     // Maximum PHEG1
  59.     //BRGCON2bits.SEG2PHTS = 1;
  60.    
  61.     // Phase_Seg1 = 2 x TQ = 1
  62.     //BRGCON2bits.SEG1PH2 = 0;
  63.     //BRGCON2bits.SEG1PH1 = 0;
  64.     //BRGCON2bits.SEG1PH0 = 1;
  65.    
  66.     // Prop_Seq = 2 x TQ = 1
  67.     //BRGCON2bits.PRSEG2 = 0;
  68.     //BRGCON2bits.PRSEG1 = 0;
  69.     //BRGCON2bits.PRSEG0 = 1;
  70.    
  71.     //  Enableing bus wake-up
  72.     //BRGCON3bits.WAKDIS = 0;
  73.    
  74.     // Dont use filter when wakeup
  75.     //BRGCON3bits.WAKFIL = 0;
  76.    
  77.     // Phase_Seg2 = 2 x TQ = 1
  78.     //BRGCON3bits.SEG2PH2 = 0;
  79.     //BRGCON3bits.SEG2PH1 = 0;
  80.     //BRGCON3bits.SEG2PH0 = 1;
  81.  
  82.     ECANCON=0;
  83.     ECANCONbits.MDSEL1 = 1; // 0  For mode 1
  84.     ECANCONbits.MDSEL0 = 0; // 1  For mode 1
  85.  
  86.  
  87.     // FILTERS AND MASKS
  88.     RXB0CONbits.RXM1=1;
  89.     RXB0CONbits.RXM0=0;
  90.  
  91.  
  92.     // INTERRUPTS
  93.    
  94.     // Diable transmit interrupt
  95.     TXBIE = 0;
  96.  
  97.     //rx any interrupt
  98.     PIR3 = 0;
  99.     PIE3 = 0b00000011;
  100.  
  101.     // High interrupt
  102.     IPR3 =0b00000011;
  103.  
  104.     // Programmable buffers interrupt
  105.     BIE0  = 0xFF;  
  106.  
  107.  
  108.     //loopback mode or not
  109.     #ifdef CAN_LOOPBACK_MODE
  110.         CANCON = 0x40;//request loopback mode
  111.         while ((CANSTAT & 0xE0) != 0x40 );//wait for loopback mode
  112.     #else
  113.         CANCON = 0x00;//request normal mode
  114.         while ((CANSTAT & 0xE0) != 0x00 );//wait for normal mode
  115.     #endif
  116.  
  117.  
  118.     // Init ticker service
  119.     tickInit();
  120.  
  121.  
  122.     // Read ID and NID if exist.
  123.     if (EERead(NODE_ID_EE)==NODE_HAS_ID)
  124.     {
  125.         MY_ID=+EERead(NODE_ID_EE + 1);
  126.     }
  127.  
  128.     // Send user program startup heatbeat
  129.     outCp.type=ptPGM;
  130.     outCp.pgm.class=pcCTRL;
  131.     outCp.pgm.id=pctAPPBOOT;
  132.     outCp.length=2;
  133.     outCp.data[1]=(BYTE)((APP_VERSION & 0xFF00)>>8);
  134.     outCp.data[0]=(BYTE)(APP_VERSION & 0xFF);
  135.     while(!canSendMessage(outCp,PRIO_HIGH));
  136. }
  137.  
  138.  
  139. /*
  140. *   Function: canISR
  141. *
  142. *   Input:  none
  143. *   Output: none
  144. *   Pre-conditions: a call to canInit()
  145. *   Affects: interrupt registers and receive data buffers
  146. *   Depends: ..
  147. */
  148. void canISR()
  149. {
  150.     ClrWdt();
  151.  
  152.     tickUpdate();
  153.  
  154.     if (PIR3bits.RXBnIF || PIR3bits.RXB1IF || PIR3bits.RXB0IF)
  155.     {
  156.         ECANCON=(ECANCON&0b00000)|(0b10000|(CANCON&0x0F));
  157.         if (RXB0CONbits.RXFUL) canGetPacket();
  158.    
  159.         if (PIR3bits.RXBnIF) {PIR3bits.RXBnIF = 0; return;}
  160.         if (PIR3bits.RXB1IF) {PIR3bits.RXB1IF = 0; return;}
  161.         if (PIR3bits.RXB0IF) {PIR3bits.RXB0IF = 0; return;}
  162.     }
  163.  
  164.    
  165.  
  166.     if ((tickGet()-heartbeat)>TICK_1S*5)
  167.     {
  168.         // Send alive heartbeat
  169.         outCp.type=ptPGM;
  170.         outCp.pgm.class=pcCTRL;
  171.         outCp.pgm.id=pctHEARTBEAT;
  172.         outCp.length=0;
  173.         canSendMessage(outCp,PRIO_HIGH);
  174.            
  175.         heartbeat = tickGet();
  176.     }
  177.  
  178.    
  179. }
  180.  
  181.  
  182. /*
  183. *   Function: canGetPacket
  184. *
  185. *   Input:  none
  186. *   Output: none
  187. *   Pre-conditions: a call to canISR and an packet is available and banked to RXB0
  188. *   Affects: Calls canParse() function in main for parsing received packet.
  189. *   Depends: none.
  190. */
  191. void canGetPacket()
  192. {
  193.         auto CAN_PACKET cp;
  194.  
  195.         //RXB0SIDH 28 27 26 25 24 23 22 21
  196.         //RXB0SIDL 20 19 18 xx xx xx 17 16
  197.         //RXB0EIDH 15 14 13 12 11 10 09 08
  198.         //RXB0EIDL 07 06 05 04 03 02 01 00
  199.  
  200.  
  201.         cp.type = (BYTE)((RXB0SIDH&0xC0)>>6);
  202.  
  203.  
  204.         if (cp.type==ptBOOT)
  205.         {
  206.             cp.boot.type  = ((RXB0SIDH&0x38)>>3);
  207.             cp.boot.offset= ((RXB0SIDH&0x7)<<5)+((RXB0SIDL&0xE0)>>3)+(RXB0SIDL&0x3);
  208.             cp.boot.rid   = RXB0EIDH;
  209.         }
  210.         else
  211.         {
  212.             cp.pgm.class= ((RXB0SIDH&0x3C)>>2);
  213.             cp.pgm.id   = (((WORD)RXB0SIDH&0x3)<<13)+(((WORD)RXB0SIDL&0xE0)<<5)+(((WORD)RXB0SIDL&0x3)<<8)+(WORD)RXB0EIDH;
  214.         }
  215.         cp.sid   = RXB0EIDL;
  216.  
  217.  
  218.         // Data length
  219.         cp.length=(RXB0DLCbits.DLC3<<3)+(RXB0DLCbits.DLC2<<2)+(RXB0DLCbits.DLC1<<1)+RXB0DLCbits.DLC0;
  220.  
  221.         // Data one bye one, for speed
  222.         cp.data[0]=RXB0D0;  cp.data[1]=RXB0D1;
  223.         cp.data[2]=RXB0D2;  cp.data[3]=RXB0D3;
  224.         cp.data[4]=RXB0D4;  cp.data[5]=RXB0D5;
  225.         cp.data[6]=RXB0D6;  cp.data[7]=RXB0D7;
  226.  
  227.         // Clear ful status
  228.         RXB0CONbits.RXFUL=0;
  229.  
  230.  
  231.  
  232.         // Check if bootloader request specific.
  233.         // reset and id change
  234.         if (cp.type==ptBOOT)
  235.         {
  236.             if (cp.boot.rid==MY_ID)
  237.             {
  238.                 if (cp.boot.type==btADDR) Reset(); // Reset me.
  239.                 if (cp.boot.type==btCHANGEID)
  240.                 {
  241.                         // Change my ID and NID
  242.                         MY_ID=cp.data[0];
  243.                         EEWrite(NODE_ID_EE+1,cp.data[0]);
  244.                         EEWrite(NODE_ID_EE,NODE_HAS_ID);
  245.                         // Send ack with new id.
  246.                         outCp.type=ptBOOT;
  247.                         outCp.boot.type=btACK;
  248.                         outCp.length=0;
  249.                         while(!canSendMessage(outCp,PRIO_HIGH));
  250.                 }
  251.             }
  252.         }
  253.  
  254.  
  255.         //Call main parser
  256.         if (cp.type==ptPGM) canParse(cp);
  257. }
  258.  
  259.  
  260. /*
  261. *   Function: canSendMessage
  262. *
  263. *   Input:  CAN_MESSAGE to send
  264. *   Output: True if packet scheduled sucess, false otherwise.
  265. *   Pre-conditions: canInit
  266. *   Affects: ..
  267. *   Depends: ..
  268. */
  269. BOOL canSendMessage(CAN_PACKET cp, CAN_PRIORITY prio)
  270. {
  271.    
  272.     if ( TXB0CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00011; }
  273.     else if ( TXB1CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00100; }
  274.     else if ( TXB2CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00101; }
  275.     else { return FALSE;}  // None of the transmit buffers were empty.
  276.  
  277.     if (prio<0 || prio>3) prio = 0;
  278.  
  279.  
  280.     //RXB0SIDH 28 27 26 25 24 23 22 21
  281.     //RXB0SIDL 20 19 18 xx xx xx 17 16
  282.     //RXB0EIDH 15 14 13 12 11 10 09 08
  283.     //RXB0EIDL 07 06 05 04 03 02 01 00
  284.  
  285.  
  286.     if (cp.type==ptBOOT)
  287.     {
  288.         RXB0SIDH = ((cp.type&0x3)<<6)+((cp.boot.type&0x7)<<3)+((cp.boot.offset&0xE0)>>5);
  289.         RXB0SIDL = ((cp.boot.offset&0x1C)<<3)+(cp.boot.offset&0x3);
  290.         RXB0EIDH = cp.boot.rid;
  291.     }
  292.     else
  293.     {
  294.         RXB0SIDH = ((cp.type&0x3)<<6)+((cp.pgm.class&0xF)<<2)+((cp.pgm.id&0x6000)>>13);
  295.         RXB0SIDL = ((cp.pgm.id&0x1C00)>>5)+((cp.pgm.id&0x300)>>8);
  296.         RXB0EIDH = (cp.pgm.id&0xFF);
  297.     }
  298.     RXB0EIDL = MY_ID;
  299.  
  300.     // Data length
  301.     RXB0DLC = 0;
  302.     if (cp.length>8) RXB0DLC=8; else RXB0DLC=cp.length;
  303.    
  304.     // NOT Remote request
  305.     _asm
  306.         bcf RXB0DLC, 6, 0
  307.     _endasm
  308.    
  309.    
  310.     // Data one bye one, for speed
  311.     RXB0D0=cp.data[0];  RXB0D1=cp.data[1];
  312.     RXB0D2=cp.data[2];  RXB0D3=cp.data[3];
  313.     RXB0D4=cp.data[4];  RXB0D5=cp.data[5];
  314.     RXB0D6=cp.data[6];  RXB0D7=cp.data[7];
  315.     // set extended
  316.     RXB0SIDLbits.EXID=1;
  317.    
  318.     // Priority
  319.     RXB0CON = (RXB0CON & 0b11111100) | prio;
  320.    
  321.     // mark as redy to transmit
  322.     _asm
  323.         bsf RXB0CON, 3, 0
  324.     _endasm
  325.    
  326.     return TRUE;
  327.  
  328. }
  329.