Subversion Repositories HomeAutomation

Rev

Rev 1751 | Rev 1910 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

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