Subversion Repositories HomeAutomation

Rev

Rev 260 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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