Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
1769 myhrman 1
/* ----------------------------------------------------------------------------
2
 * Inclusions
3
 * --------------------------------------------------------------------------*/
1449 myhrman 4
#include "sns_Serial.h"
5
 
1769 myhrman 6
 
7
/* ----------------------------------------------------------------------------
8
 * Definitions
9
 * --------------------------------------------------------------------------*/
10
#define sns_Serial_DEBUG 0
11
 
12
#ifndef min
13
#define min(_a,_b)      ((_a)<(_b) ? (_a) : (_b))
1449 myhrman 14
#endif
15
 
1769 myhrman 16
#ifndef max
17
#define max(_a,_b)      ((_a)>(_b) ? (_a) : (_b))
18
#endif
1459 arune 19
 
1769 myhrman 20
#ifndef lim
21
#define lim(_a,_minval,_maxval)     (max(min((_a),(_maxval)),(_minval)))
22
#endif
23
 
24
typedef enum {
1582 myhrman 25
    PARITY_NONE = 0,
26
    PARITY_EVEN = 1,
27
    PARITY_ODD = 2,
1769 myhrman 28
} parityMode_t;
1582 myhrman 29
 
1769 myhrman 30
 
31
/* ----------------------------------------------------------------------------
32
 * Variables
33
 * --------------------------------------------------------------------------*/
34
 
35
static uint32_t baudRate = 9600;
36
static uint16_t format = CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_RS232;
37
static uint8_t databits = 8;
38
static uint8_t stopbits = 1;
39
static parityMode_t parityMode = PARITY_NONE;
40
static uint8_t dataTimeout = 255;
1764 myhrman 41
static uint8_t packetLength = 0;
42
 
43
static struct __attribute__ ((packed)) {
44
    uint8_t prefixLength:2;
45
    uint8_t suffixLength:2;
46
    uint8_t prefixPattern[3];
47
    uint8_t suffixPattern[3];
48
} filter;
49
 
1559 arune 50
static StdCan_Msg_t msg;
51
 
1978 arune 52
#if sns_Serial_USEEEPROM==1
1769 myhrman 53
#include "sns_Serial_eeprom.h"
54
struct eeprom_sns_Serial EEMEM eeprom_sns_Serial =
55
{
56
    {
57
        9600,   // baudRate
58
        CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_LOOPBACK,    // format
59
        8,      // databits
60
        1,      // stopbits
61
        PARITY_NONE,    // parityMode
62
        255,    // dataTimeout
63
        8,      // packetLength
64
        0,      // prefixLength
65
        0,      // suffixLength
66
        {0,0,0},    // prefixPattern
67
        {0,0,0},    // suffixPattern
68
    },
69
 
70
};
1582 myhrman 71
#endif
1561 arune 72
 
1582 myhrman 73
 
1769 myhrman 74
/* ----------------------------------------------------------------------------
75
 * Internal Functions
76
 * --------------------------------------------------------------------------*/
77
static uint16_t getTimeoutValue(void)
78
{
79
    // configurations 0-250 translate directly to milliseconds (0 means DIRECT)
80
    if (dataTimeout>=0 && dataTimeout<=250) {
81
        return dataTimeout;    
82
    }
83
    // configurations 251..254 are baudrate-dependent
84
    else if (dataTimeout>=251 && dataTimeout<=254) {
85
        return (uint16_t)(baudRate/(uint32_t)1000UL*((uint32_t)dataTimeout-250UL));
86
    }
87
    // configuration 255 means use the compiled default value
88
    else {
89
        return sns_Serial_FORCE_SEND_TIME_MS;
90
    }
91
}
1582 myhrman 92
 
93
 
1769 myhrman 94
/* ----------------------------------------------------------------------------
95
 * Function Implementations
96
 * --------------------------------------------------------------------------*/
1582 myhrman 97
 
1561 arune 98
uint8_t sns_Serial_setSettings(void)
99
{
100
    uint8_t returnval = 1;
101
 
102
    if (format == CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_RS232)
103
    {
104
#if sns_Serial_DEBUG==1
105
        printf("RS232\n");
106
#endif
107
        gpio_clr_pin(sns_Serial_485_CONNECT);   // disable RS485_CONNECT
108
        gpio_clr_pin(sns_Serial_TERM_EN);       // disable termination
109
        gpio_clr_pin(sns_Serial_485_232);       // RS232 mode
110
        gpio_set_pin(sns_Serial_RXEN);          // enable RX
111
        gpio_set_pin(sns_Serial_ON);            // enable charge pump
112
    }
113
    else if (format == CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_RS485FULLDUPLEX)
114
    {
115
#if sns_Serial_DEBUG==1
116
        printf("RS485FD\n");
117
#endif
118
        gpio_clr_pin(sns_Serial_485_CONNECT);   // disable RS485_CONNECT
119
        gpio_clr_pin(sns_Serial_TERM_EN);       // disable termination
120
        gpio_set_pin(sns_Serial_485_232);       // RS485 mode
121
        gpio_set_pin(sns_Serial_RXEN);          // enable RX
122
        gpio_set_pin(sns_Serial_TXEN);          // enable TX
123
        gpio_set_pin(sns_Serial_ON);            // enable charge pump
124
    }
125
    else if (format == CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_RS485HALFDUPLEX)
126
    {
127
#if sns_Serial_DEBUG==1
128
        printf("RS485HD\n");
129
#endif
130
        gpio_set_pin(sns_Serial_485_CONNECT);   // enable RS485_CONNECT
131
        gpio_clr_pin(sns_Serial_TERM_EN);       // disable termination
132
        gpio_set_pin(sns_Serial_485_232);       // RS485 mode
133
        gpio_set_pin(sns_Serial_RXEN);          // enable RX
134
    /* TODO shoud the TX really be enabled in half duplex? */
135
        gpio_set_pin(sns_Serial_TXEN);          // enable TX
136
        gpio_set_pin(sns_Serial_ON);            // enable charge pump
137
    }
138
    else if (format == CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_RS485HALFDUPLEXWITHTERMINATION)
139
    {
140
#if sns_Serial_DEBUG==1
141
        printf("485HDT\n");
142
#endif
143
        gpio_set_pin(sns_Serial_485_CONNECT);   // enable RS485_CONNECT
144
        gpio_set_pin(sns_Serial_TERM_EN);       // enable termination
145
        gpio_set_pin(sns_Serial_485_232);       // RS485 mode
146
    /* TODO shoud the TX really be enabled in half duplex? */
147
        gpio_set_pin(sns_Serial_RXEN);          // enable RX
148
        gpio_set_pin(sns_Serial_TXEN);          // enable TX
149
        gpio_set_pin(sns_Serial_ON);            // enable charge pump
150
    }
151
    else if (format == CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_LOOPBACK)
152
    {
153
#if sns_Serial_DEBUG==1
154
        printf("LPMODE\n");
155
#endif
156
        gpio_clr_pin(sns_Serial_485_CONNECT);   // disable RS485_CONNECT
157
        gpio_clr_pin(sns_Serial_TERM_EN);       // disable termination
158
        gpio_set_pin(sns_Serial_485_232);       // RS232 mode
159
        gpio_set_pin(sns_Serial_RXEN);          // enable RX
160
        gpio_set_pin(sns_Serial_TXEN);          // enable TX
161
        gpio_clr_pin(sns_Serial_ON);            // disable charge pump (i.e. enable loopback)
162
    }
163
    else
164
    {
165
        //invalid format
166
#if sns_Serial_DEBUG==1
167
        printf("ERROR!\n");
168
#endif
169
        //return 0, not successful
170
        returnval = 0;
171
    }
172
 
173
    return returnval;
174
}
175
 
1769 myhrman 176
 
177
void sns_Serial_Init()
1449 myhrman 178
{
2178 arune 179
    /* Init filter in case eeprom not correct */
180
    filter.prefixLength = 0;
181
    filter.suffixLength = 0;
182
    filter.prefixPattern[0] = 0;
183
    filter.prefixPattern[1] = 0;
184
    filter.prefixPattern[2] = 0;
185
    filter.suffixPattern[0] = 0;
186
    filter.suffixPattern[1] = 0;
187
    filter.suffixPattern[2] = 0;
1978 arune 188
#if sns_Serial_USEEEPROM==1
1769 myhrman 189
    if (EEDATA_OK) {
190
    //if (0) {
1556 arune 191
#if ((__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ == 6 && __AVR_LIBC_REVISION__ >=2)||(__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ > 6)||__AVR_LIBC_MAJOR__ > 1)
1555 myhrman 192
        baudRate = eeprom_read_dword(EEDATA32.baudRate);
1556 arune 193
#else
194
#warning This version of AVR-libc does not have support for eeprom read dword
195
#endif
1555 myhrman 196
        format = eeprom_read_word(EEDATA16.format);
1582 myhrman 197
        databits = eeprom_read_byte(EEDATA.databits);
198
        stopbits = eeprom_read_byte(EEDATA.stopbits);
199
        parityMode = eeprom_read_byte(EEDATA.parityMode);
1764 myhrman 200
        dataTimeout = eeprom_read_byte(EEDATA.dataTimeout);
201
        packetLength = eeprom_read_byte(EEDATA.packetLength);
202
        filter.prefixLength = lim(eeprom_read_byte(EEDATA.prefixLength), 0, 3);
203
        filter.suffixLength = lim(eeprom_read_byte(EEDATA.suffixLength), 0, 3);
204
        filter.prefixPattern[0] = eeprom_read_byte(EEDATA.prefixPattern[0]);
205
        filter.prefixPattern[1] = eeprom_read_byte(EEDATA.prefixPattern[1]);
206
        filter.prefixPattern[2] = eeprom_read_byte(EEDATA.prefixPattern[2]);
207
        filter.suffixPattern[0] = eeprom_read_byte(EEDATA.suffixPattern[0]);
208
        filter.suffixPattern[1] = eeprom_read_byte(EEDATA.suffixPattern[1]);
209
        filter.suffixPattern[2] = eeprom_read_byte(EEDATA.suffixPattern[2]);
1449 myhrman 210
    }
1555 myhrman 211
    else {
212
        //The CRC of the EEPROM is not correct, store default values and update CRC
1556 arune 213
#if ((__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ == 6 && __AVR_LIBC_REVISION__ >=2)||(__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ > 6)||__AVR_LIBC_MAJOR__ > 1)
1555 myhrman 214
        eeprom_write_dword_crc(EEDATA32.baudRate, 9600, WITHOUT_CRC);
1556 arune 215
#else
216
#warning This version of AVR-libc does not have support for eeprom write dword
217
#endif
1555 myhrman 218
        eeprom_write_word_crc(EEDATA16.format, CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_LOOPBACK, WITHOUT_CRC);
1582 myhrman 219
        eeprom_write_byte_crc(EEDATA.databits, 8, WITHOUT_CRC);
220
        eeprom_write_byte_crc(EEDATA.stopbits, 1, WITHOUT_CRC);
221
        eeprom_write_byte_crc(EEDATA.parityMode, PARITY_NONE, WITHOUT_CRC);
1769 myhrman 222
        eeprom_write_byte_crc(EEDATA.dataTimeout, 255, WITHOUT_CRC);
1764 myhrman 223
        eeprom_write_byte_crc(EEDATA.packetLength, 8, WITHOUT_CRC);
224
        eeprom_write_byte_crc(EEDATA.prefixLength, 0, WITHOUT_CRC);
225
        eeprom_write_byte_crc(EEDATA.suffixLength, 0, WITHOUT_CRC);
226
        eeprom_write_byte_crc(EEDATA.prefixPattern[0], 0, WITHOUT_CRC);
227
        eeprom_write_byte_crc(EEDATA.prefixPattern[1], 0, WITHOUT_CRC);
228
        eeprom_write_byte_crc(EEDATA.prefixPattern[2], 0, WITHOUT_CRC);
229
        eeprom_write_byte_crc(EEDATA.suffixPattern[0], 0, WITHOUT_CRC);
230
        eeprom_write_byte_crc(EEDATA.suffixPattern[1], 0, WITHOUT_CRC);
231
        eeprom_write_byte_crc(EEDATA.suffixPattern[2], 0, WITHOUT_CRC);
1555 myhrman 232
        EEDATA_UPDATE_CRC;
233
    }
1459 arune 234
#endif
1582 myhrman 235
    uart_setDatabits(databits);
236
    uart_setStopbits(stopbits);
237
    uart_setParity(parityMode!=PARITY_NONE, parityMode==PARITY_ODD);
1459 arune 238
    uart_init(UART_BAUD_SELECT(baudRate, F_CPU));
1561 arune 239
 
240
    // configure control pins to outputs
1459 arune 241
    gpio_set_out(sns_Serial_RXEN);
242
    gpio_set_out(sns_Serial_TXEN);
243
    gpio_set_out(sns_Serial_ON);
244
    gpio_set_out(sns_Serial_485_232);
245
    gpio_set_out(sns_Serial_TERM_EN);
246
    gpio_set_out(sns_Serial_485_CONNECT);
1449 myhrman 247
 
1561 arune 248
    sns_Serial_setSettings();
1449 myhrman 249
 
1536 arune 250
#if sns_Serial_DEBUG==1
1475 myhrman 251
    printf("Serial started!\n");
1536 arune 252
#endif
1559 arune 253
 
254
    msg.Length = 0; // no data so far
1764 myhrman 255
 
256
    //gpio_set_pin(sns_Serial_TXEN);            // enable TX
257
    //uart_putc('7');
1449 myhrman 258
}
259
 
1769 myhrman 260
 
1449 myhrman 261
void sns_Serial_Process(void)
1459 arune 262
{
263
    StdCan_Set_class(msg.Header, CAN_MODULE_CLASS_SNS);
264
    StdCan_Set_direction(msg.Header, DIRECTIONFLAG_TO_OWNER);
265
    msg.Header.ModuleType = CAN_MODULE_TYPE_SNS_SERIAL;
266
    msg.Header.ModuleId = sns_Serial_ID;
267
    msg.Header.Command = CAN_MODULE_CMD_SERIAL_SERIALDATA;
268
 
269
    unsigned char status;
270
 
271
    do
272
    {
273
        // ask uart driver for more data
274
        unsigned int data = uart_getc();
275
        // character is contained in LSB
276
        unsigned char c = (unsigned char)(data & 0x00FF);
1769 myhrman 277
 
1459 arune 278
        // status is contained in MSB
279
        status = (unsigned char)((data & 0xFF00) >> 8);
280
 
281
        // status == 0 means we just received a new char
282
        if (status == 0)
283
        {
1536 arune 284
#if sns_Serial_DEBUG==1
1475 myhrman 285
            printf("RX\n");
1536 arune 286
#endif
1459 arune 287
            // insert it into the message
288
            msg.Data[(uint8_t)msg.Length] = c;
289
            msg.Length++;
1559 arune 290
 
1769 myhrman 291
            uint16_t timeout;
292
            if ((timeout = getTimeoutValue()) != 0) {
293
                Timer_SetTimeout(sns_Serial_FORCE_SEND_TIMER, timeout , TimerTypeOneShot, 0);
294
            }
1459 arune 295
        }
296
    // keep going until max data length reached, or until uart RXBUF is empty
1764 myhrman 297
    } while (status == 0 && msg.Length < packetLength);
1459 arune 298
 
1559 arune 299
    // check if force send or send-frame full
1769 myhrman 300
    if ((Timer_Expired(sns_Serial_FORCE_SEND_TIMER) && msg.Length>0) || msg.Length==packetLength || (getTimeoutValue()==0 && msg.Length>0))
1459 arune 301
    {
302
        // transmit this chunk of data (max 8 chars)
303
        while(StdCan_Put(&msg) != StdCan_Ret_OK);
1559 arune 304
        msg.Length = 0; // no data so far
1449 myhrman 305
    }
306
}
307
 
1769 myhrman 308
 
1449 myhrman 309
void sns_Serial_HandleMessage(StdCan_Msg_t *rxMsg)
1459 arune 310
{
1449 myhrman 311
    if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
312
        StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
313
        rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_SERIAL &&
314
        rxMsg->Header.ModuleId == sns_Serial_ID)
315
    {
316
        switch (rxMsg->Header.Command)
1459 arune 317
        {
318
            case CAN_MODULE_CMD_SERIAL_SERIALDATA:
1536 arune 319
#if sns_Serial_DEBUG==1
320
                printf("TX\n");
321
#endif
1475 myhrman 322
                gpio_set_pin(sns_Serial_TXEN);          // enable TX
1459 arune 323
                for (uint8_t i=0; i<rxMsg->Length; i++)
324
                {
325
                    uart_putc(rxMsg->Data[i]);
1452 myhrman 326
                }
1536 arune 327
                /* TODO Cannot disable TX yet, the data has only been placed in buffer but not sent */
328
//              gpio_clr_pin(sns_Serial_TXEN);          // disable TX
1452 myhrman 329
                break;
1582 myhrman 330
 
1459 arune 331
            case CAN_MODULE_CMD_SERIAL_SERIALCONFIG:
1475 myhrman 332
                baudRate = 10 * (((uint32_t)rxMsg->Data[1] << 0) | ((uint32_t)rxMsg->Data[0] << 8));
333
                format = (uint16_t)rxMsg->Data[2];
1582 myhrman 334
                databits = lim(rxMsg->Data[3], 5, 9);
335
                stopbits = lim(rxMsg->Data[4], 1, 2);
336
                parityMode = lim(rxMsg->Data[5], 0, 2);
337
                uart_setDatabits(databits);
338
                uart_setStopbits(stopbits);
339
                uart_setParity(parityMode!=PARITY_NONE, parityMode==PARITY_ODD);
1459 arune 340
                uart_init(UART_BAUD_SELECT(baudRate, F_CPU));
1561 arune 341
 
342
                uint8_t returnval = sns_Serial_setSettings();
343
 
344
                if (returnval)
1459 arune 345
                {
1555 myhrman 346
                // update EEPROM data
1978 arune 347
#if sns_Serial_USEEEPROM==1
1556 arune 348
#if ((__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ == 6 && __AVR_LIBC_REVISION__ >=2)||(__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ > 6)||__AVR_LIBC_MAJOR__ > 1)
1561 arune 349
                eeprom_write_dword_crc(EEDATA32.baudRate, baudRate, WITHOUT_CRC);
1556 arune 350
#else
351
#warning This version of AVR-libc does not have support for eeprom read dword
352
#endif
1561 arune 353
                eeprom_write_word_crc(EEDATA16.format, format, WITHOUT_CRC);
1582 myhrman 354
                eeprom_write_byte_crc(EEDATA.databits, databits, WITHOUT_CRC);
355
                eeprom_write_byte_crc(EEDATA.stopbits, stopbits, WITHOUT_CRC);
356
                eeprom_write_byte_crc(EEDATA.parityMode, parityMode, WITHOUT_CRC);
1555 myhrman 357
                EEDATA_UPDATE_CRC;
1558 arune 358
#endif
1561 arune 359
                }
1459 arune 360
                break;
1764 myhrman 361
 
362
            case CAN_MODULE_CMD_SERIAL_SERIALFILTER:
363
                dataTimeout = rxMsg->Data[0];
364
                filter.prefixLength = ((rxMsg->Data[1] & 0x0F) >> 0);
365
                filter.suffixLength = ((rxMsg->Data[1] & 0x30) >> 4);
366
                packetLength = ((rxMsg->Data[1] & 0xC0) >> 6);
367
                filter.prefixPattern[2] = rxMsg->Data[2];
368
                filter.prefixPattern[1] = rxMsg->Data[3];
369
                filter.prefixPattern[0] = rxMsg->Data[4];
370
                filter.suffixPattern[2] = rxMsg->Data[5];
371
                filter.suffixPattern[1] = rxMsg->Data[6];
372
                filter.suffixPattern[0] = rxMsg->Data[7];
373
 
374
                // update EEPROM data
375
                eeprom_write_byte_crc(EEDATA.dataTimeout, dataTimeout, WITHOUT_CRC);
376
                eeprom_write_byte_crc(EEDATA.packetLength, packetLength, WITHOUT_CRC);
377
                eeprom_write_byte_crc(EEDATA.prefixLength, filter.prefixLength, WITHOUT_CRC);
378
                eeprom_write_byte_crc(EEDATA.suffixLength, filter.suffixLength, WITHOUT_CRC);
379
                eeprom_write_byte_crc(EEDATA.prefixPattern[0], filter.prefixPattern[0], WITHOUT_CRC);
380
                eeprom_write_byte_crc(EEDATA.prefixPattern[1], filter.prefixPattern[1], WITHOUT_CRC);
381
                eeprom_write_byte_crc(EEDATA.prefixPattern[2], filter.prefixPattern[2], WITHOUT_CRC);
382
                eeprom_write_byte_crc(EEDATA.suffixPattern[0], filter.suffixPattern[0], WITHOUT_CRC);
383
                eeprom_write_byte_crc(EEDATA.suffixPattern[1], filter.suffixPattern[1], WITHOUT_CRC);
384
                eeprom_write_byte_crc(EEDATA.suffixPattern[2], filter.suffixPattern[2], WITHOUT_CRC);
385
                EEDATA_UPDATE_CRC;
386
 
387
                break;
1449 myhrman 388
        }
389
    }
390
}
391
 
1769 myhrman 392
 
1449 myhrman 393
void sns_Serial_List(uint8_t ModuleSequenceNumber)
394
{
395
    StdCan_Msg_t txMsg;
396
 
397
    StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
398
    StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
399
    txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_SERIAL;
400
    txMsg.Header.ModuleId = sns_Serial_ID;
401
    txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
402
    txMsg.Length = 6;
403
 
1910 arune 404
    uint32_t HwId=BIOS_GetHwId();
405
    txMsg.Data[0] = HwId&0xff;
406
    txMsg.Data[1] = (HwId>>8)&0xff;
407
    txMsg.Data[2] = (HwId>>16)&0xff;
408
    txMsg.Data[3] = (HwId>>24)&0xff;
1449 myhrman 409
 
410
    txMsg.Data[4] = NUMBER_OF_MODULES;
411
    txMsg.Data[5] = ModuleSequenceNumber;
412
 
413
    while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
414
}
1475 myhrman 415