Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
85 johboh 1
/*********************************************************************
2
 *
86 johboh 3
 *                  CAN module
85 johboh 4
 *
5
 *********************************************************************
86 johboh 6
 * FileName:        $HeadURL: https://svn.auml.se/svn/HomeAutomation/trunk/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 $
85 johboh 10
 ********************************************************************/
11
 
12
#include <CANdefs.h>
13
#include <stackTasks.h>
14
#include <CAN.h>
260 johboh 15
#include <EEaccess.h>
16
#include <funcdefs.h>
17
#include <Tick.h>
85 johboh 18
 
353 johboh 19
static TICK heartbeat;
260 johboh 20
static int MY_ID = DEFAULT_ID;
339 johboh 21
static CAN_PACKET outCp;
260 johboh 22
 
85 johboh 23
static void canGetPacket(void);
24
 
363 johboh 25
BYTE myId() { return MY_ID; }
85 johboh 26
 
363 johboh 27
 
85 johboh 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
 
260 johboh 44
    // 500Khz@40Mhz (new by the book)
45
    BRGCON1 = 0x04;
46
    BRGCON2 = 0xD1;
47
    BRGCON3 = 0x81;
48
 
49
    //BRGCON1=0;
85 johboh 50
 
51
    // Sync_Seq = 2 x TQ = 1
260 johboh 52
    //BRGCON1bits.SJW1=0;
53
    //BRGCON1bits.SJW0=1;
85 johboh 54
 
55
    // Setting BRP.
260 johboh 56
    //BRGCON1=BRGCON1|CAN_BRP;
85 johboh 57
 
58
    // Maximum PHEG1
260 johboh 59
    //BRGCON2bits.SEG2PHTS = 1;
85 johboh 60
 
61
    // Phase_Seg1 = 2 x TQ = 1
260 johboh 62
    //BRGCON2bits.SEG1PH2 = 0;
63
    //BRGCON2bits.SEG1PH1 = 0;
64
    //BRGCON2bits.SEG1PH0 = 1;
85 johboh 65
 
66
    // Prop_Seq = 2 x TQ = 1
260 johboh 67
    //BRGCON2bits.PRSEG2 = 0;
68
    //BRGCON2bits.PRSEG1 = 0;
69
    //BRGCON2bits.PRSEG0 = 1;
85 johboh 70
 
71
    //  Enableing bus wake-up
260 johboh 72
    //BRGCON3bits.WAKDIS = 0;
85 johboh 73
 
74
    // Dont use filter when wakeup
260 johboh 75
    //BRGCON3bits.WAKFIL = 0;
85 johboh 76
 
77
    // Phase_Seg2 = 2 x TQ = 1
260 johboh 78
    //BRGCON3bits.SEG2PH2 = 0;
79
    //BRGCON3bits.SEG2PH1 = 0;
80
    //BRGCON3bits.SEG2PH0 = 1;
85 johboh 81
 
82
    ECANCON=0;
95 johboh 83
    ECANCONbits.MDSEL1 = 1; // 0  For mode 1 
84
    ECANCONbits.MDSEL0 = 0; // 1  For mode 1 
85 johboh 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
 
260 johboh 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
    {
339 johboh 125
        MY_ID=+EERead(NODE_ID_EE + 1);
260 johboh 126
    }
127
 
128
    // Send user program startup heatbeat
339 johboh 129
    outCp.type=ptPGM;
130
    outCp.pgm.class=pcCTRL;
131
    outCp.pgm.id=pctAPPBOOT;
342 johboh 132
    outCp.length=2;
133
    outCp.data[1]=(BYTE)((APP_VERSION & 0xFF00)>>8);
134
    outCp.data[0]=(BYTE)(APP_VERSION & 0xFF);
339 johboh 135
    while(!canSendMessage(outCp,PRIO_HIGH));
85 johboh 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
{
339 johboh 150
    ClrWdt();
151
 
353 johboh 152
    tickUpdate();
153
 
85 johboh 154
    if (PIR3bits.RXBnIF || PIR3bits.RXB1IF || PIR3bits.RXB0IF)
155
    {
95 johboh 156
        ECANCON=(ECANCON&0b00000)|(0b10000|(CANCON&0x0F));
157
        if (RXB0CONbits.RXFUL) canGetPacket();
85 johboh 158
 
95 johboh 159
        if (PIR3bits.RXBnIF) {PIR3bits.RXBnIF = 0; return;}
160
        if (PIR3bits.RXB1IF) {PIR3bits.RXB1IF = 0; return;}
161
        if (PIR3bits.RXB0IF) {PIR3bits.RXB0IF = 0; return;}
85 johboh 162
    }
260 johboh 163
 
353 johboh 164
 
260 johboh 165
 
353 johboh 166
    if ((tickGet()-heartbeat)>TICK_1S*5)
260 johboh 167
    {
168
        // Send alive heartbeat
339 johboh 169
        outCp.type=ptPGM;
170
        outCp.pgm.class=pcCTRL;
171
        outCp.pgm.id=pctHEARTBEAT;
172
        outCp.length=0;
173
        canSendMessage(outCp,PRIO_HIGH);
260 johboh 174
 
175
        heartbeat = tickGet();
176
    }
177
 
339 johboh 178
 
85 johboh 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
{
363 johboh 193
        auto CAN_PACKET cp;
85 johboh 194
 
86 johboh 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
85 johboh 199
 
200
 
342 johboh 201
        cp.type = (BYTE)((RXB0SIDH&0xC0)>>6);
85 johboh 202
 
203
 
339 johboh 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);
342 johboh 213
            cp.pgm.id   = (((WORD)RXB0SIDH&0x3)<<13)+(((WORD)RXB0SIDL&0xE0)<<5)+(((WORD)RXB0SIDL&0x3)<<8)+(WORD)RXB0EIDH;
339 johboh 214
        }
215
        cp.sid   = RXB0EIDL;
85 johboh 216
 
339 johboh 217
 
85 johboh 218
        // Data length
339 johboh 219
        cp.length=(RXB0DLCbits.DLC3<<3)+(RXB0DLCbits.DLC2<<2)+(RXB0DLCbits.DLC1<<1)+RXB0DLCbits.DLC0;
85 johboh 220
 
221
        // Data one bye one, for speed
339 johboh 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;
85 johboh 226
 
227
        // Clear ful status
228
        RXB0CONbits.RXFUL=0;
229
 
260 johboh 230
 
231
 
339 johboh 232
        // Check if bootloader request specific.
260 johboh 233
        // reset and id change
339 johboh 234
        if (cp.type==ptBOOT)
260 johboh 235
        {
339 johboh 236
            if (cp.boot.rid==MY_ID)
260 johboh 237
            {
339 johboh 238
                if (cp.boot.type==btADDR) Reset(); // Reset me.
239
                if (cp.boot.type==btCHANGEID)
260 johboh 240
                {
241
                        // Change my ID and NID
339 johboh 242
                        MY_ID=cp.data[0];
243
                        EEWrite(NODE_ID_EE+1,cp.data[0]);
260 johboh 244
                        EEWrite(NODE_ID_EE,NODE_HAS_ID);
245
                        // Send ack with new id.
339 johboh 246
                        outCp.type=ptBOOT;
247
                        outCp.boot.type=btACK;
248
                        outCp.length=0;
249
                        while(!canSendMessage(outCp,PRIO_HIGH));
260 johboh 250
                }
251
            }
252
        }
253
 
254
 
85 johboh 255
        //Call main parser
339 johboh 256
        if (cp.type==ptPGM) canParse(cp);
85 johboh 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
*/
339 johboh 269
BOOL canSendMessage(CAN_PACKET cp, CAN_PRIORITY prio)
85 johboh 270
{
271
 
272
    if ( TXB0CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00011; }
353 johboh 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. 
85 johboh 276
 
277
    if (prio<0 || prio>3) prio = 0;
278
 
279
 
339 johboh 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
260 johboh 284
 
85 johboh 285
 
339 johboh 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;
85 johboh 299
 
339 johboh 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;
85 johboh 327
 
328
}