Subversion Repositories HomeAutomation

Rev

Rev 260 | Blame | Last modification | View Log | SVN | RSS feed

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