Subversion Repositories HomeAutomation

Rev

Rev 1910 | Go to most recent revision | 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
{
1978 arune 179
#if sns_Serial_USEEEPROM==1
1769 myhrman 180
    if (EEDATA_OK) {
181
    //if (0) {
1556 arune 182
#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 183
        baudRate = eeprom_read_dword(EEDATA32.baudRate);
1556 arune 184
#else
185
#warning This version of AVR-libc does not have support for eeprom read dword
186
#endif
1555 myhrman 187
        format = eeprom_read_word(EEDATA16.format);
1582 myhrman 188
        databits = eeprom_read_byte(EEDATA.databits);
189
        stopbits = eeprom_read_byte(EEDATA.stopbits);
190
        parityMode = eeprom_read_byte(EEDATA.parityMode);
1764 myhrman 191
        dataTimeout = eeprom_read_byte(EEDATA.dataTimeout);
192
        packetLength = eeprom_read_byte(EEDATA.packetLength);
193
        filter.prefixLength = lim(eeprom_read_byte(EEDATA.prefixLength), 0, 3);
194
        filter.suffixLength = lim(eeprom_read_byte(EEDATA.suffixLength), 0, 3);
195
        filter.prefixPattern[0] = eeprom_read_byte(EEDATA.prefixPattern[0]);
196
        filter.prefixPattern[1] = eeprom_read_byte(EEDATA.prefixPattern[1]);
197
        filter.prefixPattern[2] = eeprom_read_byte(EEDATA.prefixPattern[2]);
198
        filter.suffixPattern[0] = eeprom_read_byte(EEDATA.suffixPattern[0]);
199
        filter.suffixPattern[1] = eeprom_read_byte(EEDATA.suffixPattern[1]);
200
        filter.suffixPattern[2] = eeprom_read_byte(EEDATA.suffixPattern[2]);
1449 myhrman 201
    }
1555 myhrman 202
    else {
203
        //The CRC of the EEPROM is not correct, store default values and update CRC
1556 arune 204
#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 205
        eeprom_write_dword_crc(EEDATA32.baudRate, 9600, WITHOUT_CRC);
1556 arune 206
#else
207
#warning This version of AVR-libc does not have support for eeprom write dword
208
#endif
1555 myhrman 209
        eeprom_write_word_crc(EEDATA16.format, CAN_MODULE_ENUM_SERIAL_SERIALCONFIG_PHYSICALFORMAT_LOOPBACK, WITHOUT_CRC);
1582 myhrman 210
        eeprom_write_byte_crc(EEDATA.databits, 8, WITHOUT_CRC);
211
        eeprom_write_byte_crc(EEDATA.stopbits, 1, WITHOUT_CRC);
212
        eeprom_write_byte_crc(EEDATA.parityMode, PARITY_NONE, WITHOUT_CRC);
1769 myhrman 213
        eeprom_write_byte_crc(EEDATA.dataTimeout, 255, WITHOUT_CRC);
1764 myhrman 214
        eeprom_write_byte_crc(EEDATA.packetLength, 8, WITHOUT_CRC);
215
        eeprom_write_byte_crc(EEDATA.prefixLength, 0, WITHOUT_CRC);
216
        eeprom_write_byte_crc(EEDATA.suffixLength, 0, WITHOUT_CRC);
217
        eeprom_write_byte_crc(EEDATA.prefixPattern[0], 0, WITHOUT_CRC);
218
        eeprom_write_byte_crc(EEDATA.prefixPattern[1], 0, WITHOUT_CRC);
219
        eeprom_write_byte_crc(EEDATA.prefixPattern[2], 0, WITHOUT_CRC);
220
        eeprom_write_byte_crc(EEDATA.suffixPattern[0], 0, WITHOUT_CRC);
221
        eeprom_write_byte_crc(EEDATA.suffixPattern[1], 0, WITHOUT_CRC);
222
        eeprom_write_byte_crc(EEDATA.suffixPattern[2], 0, WITHOUT_CRC);
1555 myhrman 223
        EEDATA_UPDATE_CRC;
224
    }
1459 arune 225
#endif
1582 myhrman 226
    uart_setDatabits(databits);
227
    uart_setStopbits(stopbits);
228
    uart_setParity(parityMode!=PARITY_NONE, parityMode==PARITY_ODD);
1459 arune 229
    uart_init(UART_BAUD_SELECT(baudRate, F_CPU));
1561 arune 230
 
231
    // configure control pins to outputs
1459 arune 232
    gpio_set_out(sns_Serial_RXEN);
233
    gpio_set_out(sns_Serial_TXEN);
234
    gpio_set_out(sns_Serial_ON);
235
    gpio_set_out(sns_Serial_485_232);
236
    gpio_set_out(sns_Serial_TERM_EN);
237
    gpio_set_out(sns_Serial_485_CONNECT);
1449 myhrman 238
 
1561 arune 239
    sns_Serial_setSettings();
1449 myhrman 240
 
1536 arune 241
#if sns_Serial_DEBUG==1
1475 myhrman 242
    printf("Serial started!\n");
1536 arune 243
#endif
1559 arune 244
 
245
    msg.Length = 0; // no data so far
1764 myhrman 246
 
247
    //gpio_set_pin(sns_Serial_TXEN);            // enable TX
248
    //uart_putc('7');
1449 myhrman 249
}
250
 
1769 myhrman 251
 
1449 myhrman 252
void sns_Serial_Process(void)
1459 arune 253
{
254
    StdCan_Set_class(msg.Header, CAN_MODULE_CLASS_SNS);
255
    StdCan_Set_direction(msg.Header, DIRECTIONFLAG_TO_OWNER);
256
    msg.Header.ModuleType = CAN_MODULE_TYPE_SNS_SERIAL;
257
    msg.Header.ModuleId = sns_Serial_ID;
258
    msg.Header.Command = CAN_MODULE_CMD_SERIAL_SERIALDATA;
259
 
260
    unsigned char status;
261
 
262
    do
263
    {
264
        // ask uart driver for more data
265
        unsigned int data = uart_getc();
266
        // character is contained in LSB
267
        unsigned char c = (unsigned char)(data & 0x00FF);
1769 myhrman 268
 
1459 arune 269
        // status is contained in MSB
270
        status = (unsigned char)((data & 0xFF00) >> 8);
271
 
272
        // status == 0 means we just received a new char
273
        if (status == 0)
274
        {
1536 arune 275
#if sns_Serial_DEBUG==1
1475 myhrman 276
            printf("RX\n");
1536 arune 277
#endif
1459 arune 278
            // insert it into the message
279
            msg.Data[(uint8_t)msg.Length] = c;
280
            msg.Length++;
1559 arune 281
 
1769 myhrman 282
            uint16_t timeout;
283
            if ((timeout = getTimeoutValue()) != 0) {
284
                Timer_SetTimeout(sns_Serial_FORCE_SEND_TIMER, timeout , TimerTypeOneShot, 0);
285
            }
1459 arune 286
        }
287
    // keep going until max data length reached, or until uart RXBUF is empty
1764 myhrman 288
    } while (status == 0 && msg.Length < packetLength);
1459 arune 289
 
1559 arune 290
    // check if force send or send-frame full
1769 myhrman 291
    if ((Timer_Expired(sns_Serial_FORCE_SEND_TIMER) && msg.Length>0) || msg.Length==packetLength || (getTimeoutValue()==0 && msg.Length>0))
1459 arune 292
    {
293
        // transmit this chunk of data (max 8 chars)
294
        while(StdCan_Put(&msg) != StdCan_Ret_OK);
1559 arune 295
        msg.Length = 0; // no data so far
1449 myhrman 296
    }
297
}
298
 
1769 myhrman 299
 
1449 myhrman 300
void sns_Serial_HandleMessage(StdCan_Msg_t *rxMsg)
1459 arune 301
{
1449 myhrman 302
    if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
303
        StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
304
        rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_SERIAL &&
305
        rxMsg->Header.ModuleId == sns_Serial_ID)
306
    {
307
        switch (rxMsg->Header.Command)
1459 arune 308
        {
309
            case CAN_MODULE_CMD_SERIAL_SERIALDATA:
1536 arune 310
#if sns_Serial_DEBUG==1
311
                printf("TX\n");
312
#endif
1475 myhrman 313
                gpio_set_pin(sns_Serial_TXEN);          // enable TX
1459 arune 314
                for (uint8_t i=0; i<rxMsg->Length; i++)
315
                {
316
                    uart_putc(rxMsg->Data[i]);
1452 myhrman 317
                }
1536 arune 318
                /* TODO Cannot disable TX yet, the data has only been placed in buffer but not sent */
319
//              gpio_clr_pin(sns_Serial_TXEN);          // disable TX
1452 myhrman 320
                break;
1582 myhrman 321
 
1459 arune 322
            case CAN_MODULE_CMD_SERIAL_SERIALCONFIG:
1475 myhrman 323
                baudRate = 10 * (((uint32_t)rxMsg->Data[1] << 0) | ((uint32_t)rxMsg->Data[0] << 8));
324
                format = (uint16_t)rxMsg->Data[2];
1582 myhrman 325
                databits = lim(rxMsg->Data[3], 5, 9);
326
                stopbits = lim(rxMsg->Data[4], 1, 2);
327
                parityMode = lim(rxMsg->Data[5], 0, 2);
328
                uart_setDatabits(databits);
329
                uart_setStopbits(stopbits);
330
                uart_setParity(parityMode!=PARITY_NONE, parityMode==PARITY_ODD);
1459 arune 331
                uart_init(UART_BAUD_SELECT(baudRate, F_CPU));
1561 arune 332
 
333
                uint8_t returnval = sns_Serial_setSettings();
334
 
335
                if (returnval)
1459 arune 336
                {
1555 myhrman 337
                // update EEPROM data
1978 arune 338
#if sns_Serial_USEEEPROM==1
1556 arune 339
#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 340
                eeprom_write_dword_crc(EEDATA32.baudRate, baudRate, WITHOUT_CRC);
1556 arune 341
#else
342
#warning This version of AVR-libc does not have support for eeprom read dword
343
#endif
1561 arune 344
                eeprom_write_word_crc(EEDATA16.format, format, WITHOUT_CRC);
1582 myhrman 345
                eeprom_write_byte_crc(EEDATA.databits, databits, WITHOUT_CRC);
346
                eeprom_write_byte_crc(EEDATA.stopbits, stopbits, WITHOUT_CRC);
347
                eeprom_write_byte_crc(EEDATA.parityMode, parityMode, WITHOUT_CRC);
1555 myhrman 348
                EEDATA_UPDATE_CRC;
1558 arune 349
#endif
1561 arune 350
                }
1459 arune 351
                break;
1764 myhrman 352
 
353
            case CAN_MODULE_CMD_SERIAL_SERIALFILTER:
354
                dataTimeout = rxMsg->Data[0];
355
                filter.prefixLength = ((rxMsg->Data[1] & 0x0F) >> 0);
356
                filter.suffixLength = ((rxMsg->Data[1] & 0x30) >> 4);
357
                packetLength = ((rxMsg->Data[1] & 0xC0) >> 6);
358
                filter.prefixPattern[2] = rxMsg->Data[2];
359
                filter.prefixPattern[1] = rxMsg->Data[3];
360
                filter.prefixPattern[0] = rxMsg->Data[4];
361
                filter.suffixPattern[2] = rxMsg->Data[5];
362
                filter.suffixPattern[1] = rxMsg->Data[6];
363
                filter.suffixPattern[0] = rxMsg->Data[7];
364
 
365
                // update EEPROM data
366
                eeprom_write_byte_crc(EEDATA.dataTimeout, dataTimeout, WITHOUT_CRC);
367
                eeprom_write_byte_crc(EEDATA.packetLength, packetLength, WITHOUT_CRC);
368
                eeprom_write_byte_crc(EEDATA.prefixLength, filter.prefixLength, WITHOUT_CRC);
369
                eeprom_write_byte_crc(EEDATA.suffixLength, filter.suffixLength, WITHOUT_CRC);
370
                eeprom_write_byte_crc(EEDATA.prefixPattern[0], filter.prefixPattern[0], WITHOUT_CRC);
371
                eeprom_write_byte_crc(EEDATA.prefixPattern[1], filter.prefixPattern[1], WITHOUT_CRC);
372
                eeprom_write_byte_crc(EEDATA.prefixPattern[2], filter.prefixPattern[2], WITHOUT_CRC);
373
                eeprom_write_byte_crc(EEDATA.suffixPattern[0], filter.suffixPattern[0], WITHOUT_CRC);
374
                eeprom_write_byte_crc(EEDATA.suffixPattern[1], filter.suffixPattern[1], WITHOUT_CRC);
375
                eeprom_write_byte_crc(EEDATA.suffixPattern[2], filter.suffixPattern[2], WITHOUT_CRC);
376
                EEDATA_UPDATE_CRC;
377
 
378
                break;
1449 myhrman 379
        }
380
    }
381
}
382
 
1769 myhrman 383
 
1449 myhrman 384
void sns_Serial_List(uint8_t ModuleSequenceNumber)
385
{
386
    StdCan_Msg_t txMsg;
387
 
388
    StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
389
    StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
390
    txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_SERIAL;
391
    txMsg.Header.ModuleId = sns_Serial_ID;
392
    txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
393
    txMsg.Length = 6;
394
 
1910 arune 395
    uint32_t HwId=BIOS_GetHwId();
396
    txMsg.Data[0] = HwId&0xff;
397
    txMsg.Data[1] = (HwId>>8)&0xff;
398
    txMsg.Data[2] = (HwId>>16)&0xff;
399
    txMsg.Data[3] = (HwId>>24)&0xff;
1449 myhrman 400
 
401
    txMsg.Data[4] = NUMBER_OF_MODULES;
402
    txMsg.Data[5] = ModuleSequenceNumber;
403
 
404
    while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
405
}
1475 myhrman 406