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