Subversion Repositories HomeAutomation

Rev

Rev 765 | 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
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();
764 arune 210
 
211
#if MCP_CS_BIT != PB2
212
    /* If slave select is not set as output it might change SPI hw to slave
213
     * See ch 18.3.2 (18.3 SS Pin Functionality) in ATmega48/88/168-datasheet */
214
    DDRB |= (1<<PB2);
215
#endif
697 arune 216
#if USE_STDCAN == 0
127 jimmy 217
    Can_Init();
693 arune 218
#else
219
    StdCan_Init(0);
220
#endif  
63 jimmy 221
 
765 arune 222
    DDRC |= 1<<PC1 | 1<<PC0;
223
    PORTC |= (1<<PC1) | (1<<PC0);
63 jimmy 224
 
225
    sei();
226
 
693 arune 227
#if SENDTIMESTAMP == 1
697 arune 228
#if USE_STDCAN == 0
356 andfri 229
    Can_Message_t timeMsg;
697 arune 230
#else
231
    StdCan_Msg_t timeMsg;
232
#endif  
356 andfri 233
    uint32_t time = Timebase_CurrentTime();
234
    uint32_t time1 = time;
235
    uint32_t unixtime = 0;
665 arune 236
#endif
63 jimmy 237
    uint16_t rxByte;
238
    uint8_t i = 0;
239
 
665 arune 240
#if SENDTIMESTAMP == 1
697 arune 241
#if USE_STDCAN == 0
356 andfri 242
    timeMsg.ExtendedFlag = 1;
243
    timeMsg.RemoteFlag = 0;
697 arune 244
    timeMsg.DataLength = 8;
245
#else
246
    /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
247
    timeMsg.Length = 0;
248
#endif
665 arune 249
    timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
250
    //timeMsg.Id = 0; //Same thing, and lib's can.h is not updated.
251
#endif
356 andfri 252
 
697 arune 253
#if USE_STDCAN == 1
693 arune 254
    StdCan_Msg_t rxMsg;
255
#endif  
256
 
63 jimmy 257
    /* main loop */
258
    while (1) {
259
        /* any new CAN messages received? */
697 arune 260
#if USE_STDCAN == 0
665 arune 261
        if (rxMsgFull) {
693 arune 262
#else
263
        if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) {
264
#endif
380 eqlazer 265
            // Toggle activity LED
63 jimmy 266
            PORTC ^= (1<<PC1);
267
            /* send message to CanWatcher */
268
            uart_putc(UART_START_BYTE);
269
            uart_putc((uint8_t)rxMsg.Id);
270
            uart_putc((uint8_t)(rxMsg.Id>>8));
271
            uart_putc((uint8_t)(rxMsg.Id>>16));
272
            uart_putc((uint8_t)(rxMsg.Id>>24));
697 arune 273
#if USE_STDCAN == 0
63 jimmy 274
            uart_putc(rxMsg.ExtendedFlag);
275
            uart_putc(rxMsg.RemoteFlag);
276
            uart_putc(rxMsg.DataLength);
277
            for (i=0; i<8; i++) {
278
                uart_putc(rxMsg.Data.bytes[i]);
279
            }
693 arune 280
#else
281
            uart_putc(1);
282
            uart_putc(0);
283
            uart_putc(rxMsg.Length);
284
            for (i=0; i<8; i++) {
285
                uart_putc(rxMsg.Data[i]);
286
            }
287
#endif
63 jimmy 288
            uart_putc(UART_END_BYTE);
665 arune 289
 
697 arune 290
#if USE_STDCAN == 0
665 arune 291
            rxMsgFull = 0;
693 arune 292
#endif
63 jimmy 293
        }
294
 
295
        /* any UART bytes received? */
296
        rxByte = uart_getc();
297
        while (rxByte != UART_NO_DATA) {
298
            /* parse byte! */
299
            UartParseByte((uint8_t)(rxByte & 0x00FF));
300
            /* receive next */
301
            rxByte = uart_getc();
302
        }
356 andfri 303
 
665 arune 304
#if SENDTIMESTAMP == 1
356 andfri 305
        time1 = Timebase_CurrentTime();
306
        if ((time1 - time) > 1000) {
307
            time = time1;
697 arune 308
#if USE_STDCAN == 0
356 andfri 309
            timeMsg.Data.dwords[0] = ++unixtime;
310
            IncTime();
311
            timeMsg.Data.dwords[1] = date.packed;
312
            Can_Send(&timeMsg);
697 arune 313
#else
314
            /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
315
            StdCan_Put(&timeMsg);
316
#endif
356 andfri 317
        }
665 arune 318
#endif
63 jimmy 319
    }
320
 
321
    return 0;
322
}