Subversion Repositories HomeAutomation

Rev

Rev 889 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
63 jimmy 1
/**
2
 * CAN test program.
3
 *
4
 * @target  AVR
5
 * @date    2006-10-29
380 eqlazer 6
 * @author  Jimmy Myhrman, Andreas Fritiofsson
63 jimmy 7
 *  
8
 */
9
 
10
/*-----------------------------------------------------------------------------
11
 * Includes
12
 *---------------------------------------------------------------------------*/
693 arune 13
 
63 jimmy 14
/* system files */
15
#include <avr/io.h>
16
#include <avr/interrupt.h>
17
#include <avr/wdt.h>
356 andfri 18
#include <avr/eeprom.h>
63 jimmy 19
#include <stdio.h>
665 arune 20
#include <string.h>
693 arune 21
 
698 arune 22
#include <canid.h>
693 arune 23
#include <config.h>
63 jimmy 24
/* lib files */
697 arune 25
#if USE_STDCAN == 1
693 arune 26
#include <stdcan.h>
27
#else
665 arune 28
#include <mcp2515.h>
693 arune 29
#endif
149 jimmy 30
#include <serial.h>
63 jimmy 31
#include <uart.h>
32
#include <timebase.h>
33
 
697 arune 34
 
35
#if USE_STDCAN == 1
693 arune 36
#if SENDTIMESTAMP == 1
697 arune 37
#warning SENDTIMESTAMP not fully implemented with StdCan yet.
693 arune 38
#endif
39
#endif
63 jimmy 40
 
693 arune 41
 
63 jimmy 42
/*-----------------------------------------------------------------------------
43
 * Defines
44
 *---------------------------------------------------------------------------*/
45
#define UART_START_BYTE 253
46
#define UART_END_BYTE 250
889 arune 47
#define UART_PING_BYTE 251
63 jimmy 48
 
697 arune 49
#if USE_STDCAN == 0
665 arune 50
volatile Can_Message_t rxMsg; // Message storage
51
volatile uint8_t rxMsgFull;   // Synchronization flag
693 arune 52
#endif
665 arune 53
 
356 andfri 54
const uint8_t days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
63 jimmy 55
 
356 andfri 56
union {
57
    uint32_t packed;
58
    struct date_t {
59
        unsigned ss:6;
60
        unsigned mm:6;
61
        unsigned hh:5;
62
        unsigned DD:5;
63
        unsigned MM:4;
64
        unsigned YY:6;
65
    } unpacked;
66
} date;
67
 
665 arune 68
#if SENDTIMESTAMP == 1
356 andfri 69
void IncTime(void) {
70
    static uint8_t YY=07, MM=03, DD=02, hh=23, mm=58, ss=00;
71
 
72
    if (ss++ > 59) {
73
        ss=0;
74
        if (mm++ > 59) {
75
            mm=0;
76
            if (hh++ > 23) {
77
                hh=0;
380 eqlazer 78
                if (DD++ > days[MM-1] + ((YY%4) & (MM==2)) ? 1 : 0) {
356 andfri 79
                    DD=1;
80
                    if (MM++ > 12) {
81
                        MM=1; YY++;
82
                    }
83
                }
84
            }
85
        }
86
    }
87
    date.unpacked.YY = YY;
88
    date.unpacked.MM = MM;
89
    date.unpacked.DD = DD;
90
    date.unpacked.hh = hh;
91
    date.unpacked.mm = mm;
92
    date.unpacked.ss = ss;
93
}
665 arune 94
#endif
63 jimmy 95
/*-----------------------------------------------------------------------------
96
 * Functions
97
 *---------------------------------------------------------------------------*/
98
/**
99
 * Parses an incoming UART byte by maintaining a state machine. The UART
100
 * bytes will build up a CAN message according to the protocol described here:
101
 *
102
 * http://www.arune.se/projekt/doku.php?id=homeautomation:pc-mjukvara
103
 *
104
 * @param c
105
 *      The received UART byte.
106
 */
107
void UartParseByte(uint8_t c) {
697 arune 108
#if USE_STDCAN == 0
127 jimmy 109
    static Can_Message_t cm;
693 arune 110
#else
111
    static StdCan_Msg_t cm;
112
#endif
63 jimmy 113
    static uint8_t waitingMessage = 0;
114
    static uint32_t startTime = 0;
115
    static int8_t count = 0;
116
 
117
    /* 50ms timeout */
127 jimmy 118
    if (waitingMessage && Timebase_PassedTimeMillis(startTime) > 50) {
63 jimmy 119
        waitingMessage = 0;
69 jimmy 120
    }
63 jimmy 121
 
122
    if (waitingMessage) {
123
        /* save start time */
127 jimmy 124
        startTime = Timebase_CurrentTime();
63 jimmy 125
        /* UART END */
126
        if (count >= 15) {
69 jimmy 127
            if (c == UART_END_BYTE) {
128
                PORTC ^= (1<<PC0);
697 arune 129
#if USE_STDCAN == 0
127 jimmy 130
                Can_Send(&cm);
693 arune 131
#else
132
                StdCan_Put(&cm);
133
#endif
69 jimmy 134
            }
63 jimmy 135
            waitingMessage = 0;
136
            return;
137
        }
138
        /* data */
139
        else if (count >= 7) {
697 arune 140
#if USE_STDCAN == 0
63 jimmy 141
            cm.Data.bytes[count-7] = c;
693 arune 142
#else
143
            cm.Data[count-7] = c;
144
#endif
63 jimmy 145
            count++;
146
            return;
147
        }
148
        /* data length */
149
        else if (count >= 6) {
697 arune 150
#if USE_STDCAN == 0
63 jimmy 151
            cm.DataLength = c;
693 arune 152
#else
153
            cm.Length = c;
154
#endif
63 jimmy 155
            count++;
156
            return;
157
        }
158
        /* remote request flag */
159
        else if (count >= 5) {
697 arune 160
#if USE_STDCAN == 0
63 jimmy 161
            cm.RemoteFlag = c;
693 arune 162
#endif
63 jimmy 163
            count++;
164
            return;
165
        }
166
        /* extended */
167
        else if (count >= 4) {
697 arune 168
#if USE_STDCAN == 0
63 jimmy 169
            cm.ExtendedFlag = c;
693 arune 170
#endif
63 jimmy 171
            count++;
172
            return;
173
        }
174
        /* ident */
175
        else if (count >= 0) {
176
            cm.Id += ((uint32_t)c << (count*8));
177
            count++;
178
            return;
179
        }
180
    }
181
 
182
    if (c == UART_START_BYTE && !waitingMessage) {
183
        waitingMessage = 1;
127 jimmy 184
        startTime = Timebase_CurrentTime();
63 jimmy 185
        count = 0;
186
        cm.Id = 0;
187
        return;
188
    }
889 arune 189
 
190
    if (c == UART_PING_BYTE && !waitingMessage) {
191
        //send ping reply
192
        uart_putc(UART_PING_BYTE);
193
        return;
194
    }
63 jimmy 195
}
196
 
697 arune 197
#if USE_STDCAN == 0
665 arune 198
void Can_Process(Can_Message_t* msg) {
199
    if (!(msg->ExtendedFlag)) return; // We don't care about standard CAN frames.
63 jimmy 200
 
665 arune 201
    if (!rxMsgFull) {
202
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
203
        rxMsgFull = 1;
204
    }
205
}
693 arune 206
#endif
665 arune 207
 
208
 
63 jimmy 209
/*-----------------------------------------------------------------------------
210
 * Main Program
211
 *---------------------------------------------------------------------------*/
212
int main(void) {
380 eqlazer 213
//  For calibrating internal oscillator
214
//  OSCCAL = eeprom_read_byte(0);
127 jimmy 215
    Timebase_Init();
149 jimmy 216
    Serial_Init();
764 arune 217
 
218
#if MCP_CS_BIT != PB2
219
    /* If slave select is not set as output it might change SPI hw to slave
220
     * See ch 18.3.2 (18.3 SS Pin Functionality) in ATmega48/88/168-datasheet */
221
    DDRB |= (1<<PB2);
222
#endif
697 arune 223
#if USE_STDCAN == 0
127 jimmy 224
    Can_Init();
693 arune 225
#else
226
    StdCan_Init(0);
227
#endif  
63 jimmy 228
 
765 arune 229
    DDRC |= 1<<PC1 | 1<<PC0;
230
    PORTC |= (1<<PC1) | (1<<PC0);
63 jimmy 231
 
232
    sei();
233
 
693 arune 234
#if SENDTIMESTAMP == 1
697 arune 235
#if USE_STDCAN == 0
356 andfri 236
    Can_Message_t timeMsg;
697 arune 237
#else
238
    StdCan_Msg_t timeMsg;
239
#endif  
356 andfri 240
    uint32_t time = Timebase_CurrentTime();
241
    uint32_t time1 = time;
242
    uint32_t unixtime = 0;
665 arune 243
#endif
63 jimmy 244
    uint16_t rxByte;
245
    uint8_t i = 0;
246
 
665 arune 247
#if SENDTIMESTAMP == 1
697 arune 248
#if USE_STDCAN == 0
356 andfri 249
    timeMsg.ExtendedFlag = 1;
250
    timeMsg.RemoteFlag = 0;
697 arune 251
    timeMsg.DataLength = 8;
252
#else
253
    /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
1266 pengi 254
    timeMsg.Length = 4;
697 arune 255
#endif
665 arune 256
    timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
257
    //timeMsg.Id = 0; //Same thing, and lib's can.h is not updated.
258
#endif
356 andfri 259
 
697 arune 260
#if USE_STDCAN == 1
693 arune 261
    StdCan_Msg_t rxMsg;
262
#endif  
263
 
63 jimmy 264
    /* main loop */
265
    while (1) {
266
        /* any new CAN messages received? */
697 arune 267
#if USE_STDCAN == 0
665 arune 268
        if (rxMsgFull) {
693 arune 269
#else
270
        if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) {
271
#endif
380 eqlazer 272
            // Toggle activity LED
63 jimmy 273
            PORTC ^= (1<<PC1);
274
            /* send message to CanWatcher */
275
            uart_putc(UART_START_BYTE);
276
            uart_putc((uint8_t)rxMsg.Id);
277
            uart_putc((uint8_t)(rxMsg.Id>>8));
278
            uart_putc((uint8_t)(rxMsg.Id>>16));
279
            uart_putc((uint8_t)(rxMsg.Id>>24));
697 arune 280
#if USE_STDCAN == 0
63 jimmy 281
            uart_putc(rxMsg.ExtendedFlag);
282
            uart_putc(rxMsg.RemoteFlag);
283
            uart_putc(rxMsg.DataLength);
284
            for (i=0; i<8; i++) {
285
                uart_putc(rxMsg.Data.bytes[i]);
286
            }
693 arune 287
#else
288
            uart_putc(1);
289
            uart_putc(0);
290
            uart_putc(rxMsg.Length);
291
            for (i=0; i<8; i++) {
292
                uart_putc(rxMsg.Data[i]);
293
            }
294
#endif
63 jimmy 295
            uart_putc(UART_END_BYTE);
665 arune 296
 
697 arune 297
#if USE_STDCAN == 0
665 arune 298
            rxMsgFull = 0;
693 arune 299
#endif
63 jimmy 300
        }
301
 
302
        /* any UART bytes received? */
303
        rxByte = uart_getc();
304
        while (rxByte != UART_NO_DATA) {
305
            /* parse byte! */
306
            UartParseByte((uint8_t)(rxByte & 0x00FF));
307
            /* receive next */
308
            rxByte = uart_getc();
309
        }
356 andfri 310
 
665 arune 311
#if SENDTIMESTAMP == 1
356 andfri 312
        time1 = Timebase_CurrentTime();
313
        if ((time1 - time) > 1000) {
314
            time = time1;
697 arune 315
#if USE_STDCAN == 0
356 andfri 316
            timeMsg.Data.dwords[0] = ++unixtime;
317
            IncTime();
318
            timeMsg.Data.dwords[1] = date.packed;
319
            Can_Send(&timeMsg);
697 arune 320
#else
321
            /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
1266 pengi 322
            unixtime++;
323
            timeMsg.Data[0] =  unixtime     & 0xFF;
324
            timeMsg.Data[1] = (unixtime>> 8)& 0xFF;
325
            timeMsg.Data[2] = (unixtime>>16)& 0xFF;
326
            timeMsg.Data[3] = (unixtime>>24)& 0xFF;
697 arune 327
            StdCan_Put(&timeMsg);
328
#endif
356 andfri 329
        }
665 arune 330
#endif
63 jimmy 331
    }
332
 
333
    return 0;
334
}