Subversion Repositories HomeAutomation

Rev

Go to most recent revision | Details | 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
47
 
697 arune 48
#if USE_STDCAN == 0
665 arune 49
volatile Can_Message_t rxMsg; // Message storage
50
volatile uint8_t rxMsgFull;   // Synchronization flag
693 arune 51
#endif
665 arune 52
 
356 andfri 53
const uint8_t days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
63 jimmy 54
 
356 andfri 55
union {
56
    uint32_t packed;
57
    struct date_t {
58
        unsigned ss:6;
59
        unsigned mm:6;
60
        unsigned hh:5;
61
        unsigned DD:5;
62
        unsigned MM:4;
63
        unsigned YY:6;
64
    } unpacked;
65
} date;
66
 
665 arune 67
#if SENDTIMESTAMP == 1
356 andfri 68
void IncTime(void) {
69
    static uint8_t YY=07, MM=03, DD=02, hh=23, mm=58, ss=00;
70
 
71
    if (ss++ > 59) {
72
        ss=0;
73
        if (mm++ > 59) {
74
            mm=0;
75
            if (hh++ > 23) {
76
                hh=0;
380 eqlazer 77
                if (DD++ > days[MM-1] + ((YY%4) & (MM==2)) ? 1 : 0) {
356 andfri 78
                    DD=1;
79
                    if (MM++ > 12) {
80
                        MM=1; YY++;
81
                    }
82
                }
83
            }
84
        }
85
    }
86
    date.unpacked.YY = YY;
87
    date.unpacked.MM = MM;
88
    date.unpacked.DD = DD;
89
    date.unpacked.hh = hh;
90
    date.unpacked.mm = mm;
91
    date.unpacked.ss = ss;
92
}
665 arune 93
#endif
63 jimmy 94
/*-----------------------------------------------------------------------------
95
 * Functions
96
 *---------------------------------------------------------------------------*/
97
/**
98
 * Parses an incoming UART byte by maintaining a state machine. The UART
99
 * bytes will build up a CAN message according to the protocol described here:
100
 *
101
 * http://www.arune.se/projekt/doku.php?id=homeautomation:pc-mjukvara
102
 *
103
 * @param c
104
 *      The received UART byte.
105
 */
106
void UartParseByte(uint8_t c) {
697 arune 107
#if USE_STDCAN == 0
127 jimmy 108
    static Can_Message_t cm;
693 arune 109
#else
110
    static StdCan_Msg_t cm;
111
#endif
63 jimmy 112
    static uint8_t waitingMessage = 0;
113
    static uint32_t startTime = 0;
114
    static int8_t count = 0;
115
 
116
    /* 50ms timeout */
127 jimmy 117
    if (waitingMessage && Timebase_PassedTimeMillis(startTime) > 50) {
63 jimmy 118
        waitingMessage = 0;
69 jimmy 119
    }
63 jimmy 120
 
121
    if (waitingMessage) {
122
        /* save start time */
127 jimmy 123
        startTime = Timebase_CurrentTime();
63 jimmy 124
        /* UART END */
125
        if (count >= 15) {
69 jimmy 126
            if (c == UART_END_BYTE) {
127
                PORTC ^= (1<<PC0);
697 arune 128
#if USE_STDCAN == 0
127 jimmy 129
                Can_Send(&cm);
693 arune 130
#else
131
                StdCan_Put(&cm);
132
#endif
69 jimmy 133
            }
63 jimmy 134
            waitingMessage = 0;
135
            return;
136
        }
137
        /* data */
138
        else if (count >= 7) {
697 arune 139
#if USE_STDCAN == 0
63 jimmy 140
            cm.Data.bytes[count-7] = c;
693 arune 141
#else
142
            cm.Data[count-7] = c;
143
#endif
63 jimmy 144
            count++;
145
            return;
146
        }
147
        /* data length */
148
        else if (count >= 6) {
697 arune 149
#if USE_STDCAN == 0
63 jimmy 150
            cm.DataLength = c;
693 arune 151
#else
152
            cm.Length = c;
153
#endif
63 jimmy 154
            count++;
155
            return;
156
        }
157
        /* remote request flag */
158
        else if (count >= 5) {
697 arune 159
#if USE_STDCAN == 0
63 jimmy 160
            cm.RemoteFlag = c;
693 arune 161
#endif
63 jimmy 162
            count++;
163
            return;
164
        }
165
        /* extended */
166
        else if (count >= 4) {
697 arune 167
#if USE_STDCAN == 0
63 jimmy 168
            cm.ExtendedFlag = c;
693 arune 169
#endif
63 jimmy 170
            count++;
171
            return;
172
        }
173
        /* ident */
174
        else if (count >= 0) {
175
            cm.Id += ((uint32_t)c << (count*8));
176
            count++;
177
            return;
178
        }
179
    }
180
 
181
    if (c == UART_START_BYTE && !waitingMessage) {
182
        waitingMessage = 1;
127 jimmy 183
        startTime = Timebase_CurrentTime();
63 jimmy 184
        count = 0;
185
        cm.Id = 0;
186
        return;
187
    }
188
}
189
 
697 arune 190
#if USE_STDCAN == 0
665 arune 191
void Can_Process(Can_Message_t* msg) {
192
    if (!(msg->ExtendedFlag)) return; // We don't care about standard CAN frames.
63 jimmy 193
 
665 arune 194
    if (!rxMsgFull) {
195
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
196
        rxMsgFull = 1;
197
    }
198
}
693 arune 199
#endif
665 arune 200
 
201
 
63 jimmy 202
/*-----------------------------------------------------------------------------
203
 * Main Program
204
 *---------------------------------------------------------------------------*/
205
int main(void) {
380 eqlazer 206
//  For calibrating internal oscillator
207
//  OSCCAL = eeprom_read_byte(0);
127 jimmy 208
    Timebase_Init();
149 jimmy 209
    Serial_Init();
697 arune 210
#if USE_STDCAN == 0
127 jimmy 211
    Can_Init();
693 arune 212
#else
213
    StdCan_Init(0);
214
#endif  
63 jimmy 215
 
216
    DDRC = 1<<PC1 | 1<<PC0;
217
    PORTC = (1<<PC1) | (1<<PC0);
218
 
219
    sei();
220
 
693 arune 221
#if SENDTIMESTAMP == 1
697 arune 222
#if USE_STDCAN == 0
356 andfri 223
    Can_Message_t timeMsg;
697 arune 224
#else
225
    StdCan_Msg_t timeMsg;
226
#endif  
356 andfri 227
    uint32_t time = Timebase_CurrentTime();
228
    uint32_t time1 = time;
229
    uint32_t unixtime = 0;
665 arune 230
#endif
63 jimmy 231
    uint16_t rxByte;
232
    uint8_t i = 0;
233
 
665 arune 234
#if SENDTIMESTAMP == 1
697 arune 235
#if USE_STDCAN == 0
356 andfri 236
    timeMsg.ExtendedFlag = 1;
237
    timeMsg.RemoteFlag = 0;
697 arune 238
    timeMsg.DataLength = 8;
239
#else
240
    /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
241
    timeMsg.Length = 0;
242
#endif
665 arune 243
    timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
244
    //timeMsg.Id = 0; //Same thing, and lib's can.h is not updated.
245
#endif
356 andfri 246
 
697 arune 247
#if USE_STDCAN == 1
693 arune 248
    StdCan_Msg_t rxMsg;
249
#endif  
250
 
63 jimmy 251
    /* main loop */
252
    while (1) {
253
        /* any new CAN messages received? */
697 arune 254
#if USE_STDCAN == 0
665 arune 255
        if (rxMsgFull) {
693 arune 256
#else
257
        if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) {
258
#endif
380 eqlazer 259
            // Toggle activity LED
63 jimmy 260
            PORTC ^= (1<<PC1);
261
            /* send message to CanWatcher */
262
            uart_putc(UART_START_BYTE);
263
            uart_putc((uint8_t)rxMsg.Id);
264
            uart_putc((uint8_t)(rxMsg.Id>>8));
265
            uart_putc((uint8_t)(rxMsg.Id>>16));
266
            uart_putc((uint8_t)(rxMsg.Id>>24));
697 arune 267
#if USE_STDCAN == 0
63 jimmy 268
            uart_putc(rxMsg.ExtendedFlag);
269
            uart_putc(rxMsg.RemoteFlag);
270
            uart_putc(rxMsg.DataLength);
271
            for (i=0; i<8; i++) {
272
                uart_putc(rxMsg.Data.bytes[i]);
273
            }
693 arune 274
#else
275
            uart_putc(1);
276
            uart_putc(0);
277
            uart_putc(rxMsg.Length);
278
            for (i=0; i<8; i++) {
279
                uart_putc(rxMsg.Data[i]);
280
            }
281
#endif
63 jimmy 282
            uart_putc(UART_END_BYTE);
665 arune 283
 
697 arune 284
#if USE_STDCAN == 0
665 arune 285
            rxMsgFull = 0;
693 arune 286
#endif
63 jimmy 287
        }
288
 
289
        /* any UART bytes received? */
290
        rxByte = uart_getc();
291
        while (rxByte != UART_NO_DATA) {
292
            /* parse byte! */
293
            UartParseByte((uint8_t)(rxByte & 0x00FF));
294
            /* receive next */
295
            rxByte = uart_getc();
296
        }
356 andfri 297
 
665 arune 298
#if SENDTIMESTAMP == 1
356 andfri 299
        time1 = Timebase_CurrentTime();
300
        if ((time1 - time) > 1000) {
301
            time = time1;
697 arune 302
#if USE_STDCAN == 0
356 andfri 303
            timeMsg.Data.dwords[0] = ++unixtime;
304
            IncTime();
305
            timeMsg.Data.dwords[1] = date.packed;
306
            Can_Send(&timeMsg);
697 arune 307
#else
308
            /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
309
            StdCan_Put(&timeMsg);
310
#endif
356 andfri 311
        }
665 arune 312
#endif
63 jimmy 313
    }
314
 
315
    return 0;
316
}