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