Subversion Repositories HomeAutomation

Rev

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

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