Subversion Repositories HomeAutomation

Rev

Rev 1686 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  *
  3.  *
  4.  *
  5.  * @date    2006-11-21
  6.  * @author  Jimmy Myhrman, Anders Runeson
  7.  *  
  8.  */
  9.  
  10. /*-----------------------------------------------------------------------------
  11.  * Includes
  12.  *---------------------------------------------------------------------------*/
  13. /* system files */
  14. #include <avr/io.h>
  15. #include <avr/interrupt.h>
  16. #include <avr/wdt.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19.  
  20. #include <canid.h>
  21. #include <config.h>
  22. /* lib files */
  23. #if USE_STDCAN == 1
  24. #include <stdcan.h>
  25. #else
  26. #include <mcp2515.h>
  27. #endif
  28. //#include <serial.h>
  29. #include <timebase.h>
  30. #include <mcu.h>
  31. #include <ip_arp_udp_tcp.h>
  32. #include <enc28j60.h>
  33. #include <timeout.h>
  34. #include <avr_compat.h>
  35. #include <net.h>
  36.  
  37. static uint8_t mymac[6] = {ENC28J60_MAC1,ENC28J60_MAC2,ENC28J60_MAC3,ENC28J60_MAC4,ENC28J60_MAC5,ENC28J60_MAC6};
  38. //static uint8_t myip[4] = {192,168,0,50};
  39. static uint8_t myip[4] = {ENC28J60_IP1,ENC28J60_IP2,ENC28J60_IP3,ENC28J60_IP4};
  40. static uint16_t rmCan2SerPrt =1100; // remote port for Can2Serial-data
  41. static uint16_t locCan2SerPrt =1100; // listen port for Can2Serial-data
  42. static uint8_t gotcan2serserver = 0;
  43.  
  44. static uint8_t prgremotemac[6];
  45. static uint8_t prgremoteip[4];
  46.  
  47. #define BUFFER_SIZE 250
  48. static uint8_t buf[BUFFER_SIZE+1];
  49.  
  50. static uint8_t buffpoint;
  51.  
  52. #define C2S_START_BYTE 253
  53. #define C2S_END_BYTE 250
  54. #define C2S_PING_BYTE 251
  55.  
  56. #if USE_STDCAN == 0
  57. volatile Can_Message_t rxMsg; // Message storage
  58. volatile uint8_t rxMsgFull;   // Synchronization flag
  59. #endif
  60.  
  61.  
  62. /*
  63. #define SEND_BUFFER_SIZE 20
  64. static char sendbuf[SEND_BUFFER_SIZE+1];
  65. static uint16_t locDumperPrt =1200; // listen port
  66. static uint8_t gotdumpserver = 0;
  67. static uint16_t rmDumperPrt =1200; // remote port for dumping data
  68. static uint8_t remotemac[6];
  69. static uint8_t remoteip[4];
  70. */
  71. /*----------------------------------------------------------------------------
  72.  * Putchar for udp
  73.  * Implements a small buffer, sends packet over udp if buffer is full or
  74.  * \n-char is sent.
  75.  * Needs a timeout to force send.
  76.  *--------------------------------------------------------------------------*/
  77. /*int udp_putchar(char c, FILE* stream) {
  78.     if (gotdumpserver != 0) {
  79.         sendbuf[buffpoint] = c;
  80.         buffpoint++;
  81.        
  82.         if (c == '\n' || buffpoint > SEND_BUFFER_SIZE) {
  83.             send_udp(buf, sendbuf, buffpoint, rmDumperPrt, remotemac, remoteip);
  84.             buffpoint = 0;
  85.         }
  86.     }
  87.     return 0;
  88. }
  89.  
  90. static FILE mystdout = FDEV_SETUP_STREAM(udp_putchar, NULL, _FDEV_SETUP_WRITE);
  91. */
  92.  
  93. #if USE_STDCAN == 0
  94. void Can_Process(Can_Message_t* msg) {
  95.     if (!(msg->ExtendedFlag)) return; // We don't care about standard CAN frames.
  96.  
  97.     if (!rxMsgFull) {
  98.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  99.         rxMsgFull = 1;
  100.     }
  101. }
  102. #endif
  103.  
  104. /*-----------------------------------------------------------------------------
  105.  * Main Program
  106.  *---------------------------------------------------------------------------*/
  107. int main(void) {
  108.  
  109. #if MCP_CS_BIT != PB2
  110.     /* If slave select is not set as output it might change SPI hw to slave
  111.      * See ch 18.3.2 (18.3 SS Pin Functionality) in ATmega48/88/168-datasheet */
  112.     DDRB |= (1<<PB2);
  113. #endif
  114.  
  115.  
  116.     //ethernet vars
  117.     uint16_t plen = 0;
  118.     uint8_t payloadlen=0;
  119.     buffpoint = 0;
  120.    
  121.     //can vars
  122.    
  123.     uint32_t timeStamp = 0;
  124.  
  125.     //uint8_t sw=0;
  126.     // LED
  127.     /* enable PB1, LED as output */
  128.     //DDRB|= (1<<DDB0);
  129.    
  130.     /* set output to Vcc, LED off */
  131.     //PORTB|= (1<<PB0);
  132.    
  133.     Mcu_Init();
  134.     Timebase_Init();
  135.  
  136.     //alla printf ska skriva till udp
  137.     //stdout = &mystdout;    //set the output stream
  138.  
  139. #if USE_STDCAN == 0
  140.     Can_Init();
  141.     Can_Message_t txMsg;
  142.     txMsg.RemoteFlag = 0;
  143.     txMsg.ExtendedFlag = 1;
  144.     rxMsgFull = 0;
  145. #else
  146.     StdCan_Init(0);
  147.     StdCan_Msg_t txMsg;
  148.     StdCan_Msg_t rxMsg;
  149. #endif
  150.  
  151.     sei();
  152.  
  153.     /* initialize enc28j60 */
  154.     if (enc28j60Init(mymac) != 1) {
  155.         /* Great place to set an IO for debug */
  156.     }
  157.     delay_ms(20);
  158.    
  159.     /* Magjack leds configuration, see enc28j60 datasheet, page 11 */
  160.     // LEDB=yellow LEDA=green
  161.     //
  162.     // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
  163.     enc28j60PhyWrite(PHLCON,0x476);
  164.     delay_ms(20);
  165.    
  166.     //init the ethernet/ip layer:
  167.     init_ip_arp_udp_tcp(mymac,myip,80);
  168.  
  169.     /* main loop */
  170.     while (1) {
  171.         /* service the CAN routines */
  172.        
  173. #if SENDTIMESTAMP == 1
  174.         /* send CAN message and check for CAN errors once every second */
  175.         if (Timebase_PassedTimeMillis(timeStamp) >= 1000) {
  176.             timeStamp = Timebase_CurrentTime();
  177.  
  178.             /* send timestamp, to keep network alive */
  179.             txMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
  180. #if USE_STDCAN == 0
  181.             txMsg.DataLength = 0;
  182.             Can_Send(&txMsg);
  183. #else
  184.             txMsg.Length = 0;
  185.             StdCan_Put(&txMsg);
  186. #endif
  187.         }
  188. #endif
  189.        
  190.         /* check if any messages have been received */
  191. #if USE_STDCAN == 0
  192.         if (rxMsgFull) {
  193. #else
  194.         if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) {
  195. #endif
  196.             uint8_t i;
  197.             /* Do we have any ip to send the can data to yet? */
  198.             if (gotcan2serserver != 0) {
  199.                 /* Send can frame raw in an udp packet */
  200.                 char sendbuf2[17];
  201.                
  202.                 sendbuf2[0] = C2S_START_BYTE;
  203.                 sendbuf2[1] = (uint8_t)rxMsg.Id;
  204.                 sendbuf2[2] = (uint8_t)(rxMsg.Id>>8);
  205.                 sendbuf2[3] = (uint8_t)(rxMsg.Id>>16);
  206.                 sendbuf2[4] = (uint8_t)(rxMsg.Id>>24);
  207. #if USE_STDCAN == 0
  208.                 sendbuf2[5] = rxMsg.ExtendedFlag;
  209.                 sendbuf2[6] = rxMsg.RemoteFlag;
  210.                 sendbuf2[7] = rxMsg.DataLength;
  211.                 for (i=0; i<8; i++) {
  212.                     sendbuf2[8+i] = rxMsg.Data.bytes[i];
  213.                 }
  214. #else
  215.                 sendbuf2[5] = 1;
  216.                 sendbuf2[6] = 0;
  217.                 sendbuf2[7] = rxMsg.Length;
  218.                 for (i=0; i<8; i++) {
  219.                     sendbuf2[8+i] = rxMsg.Data[i];
  220.                 }
  221. #endif
  222.                 sendbuf2[16] = C2S_END_BYTE;
  223.                
  224. #ifndef ENC28J60_USART_SPI_MODE
  225.                 //MCP_INT_DISABLE();
  226.                 cli();
  227. #endif
  228.                 send_udp(buf, sendbuf2, 18, rmCan2SerPrt, prgremotemac, prgremoteip);
  229. #ifndef ENC28J60_USART_SPI_MODE
  230.                 sei();
  231.                 //MCP_INT_ENABLE();
  232. #endif
  233.             }
  234.            
  235. #if USE_STDCAN == 0
  236.             rxMsgFull = 0;
  237. #endif
  238.         }
  239.        
  240.         //test-debug-kod
  241.         if ((enc28j60Read(EIR) & EIR_TXERIF)) {
  242.             //printf("EIR_TXERIF set!\n");
  243.             if ((enc28j60Read(ECON1) & ECON1_TXRTS)) {
  244.                 //printf("ECON1_TXRTS set!\n");
  245.             }
  246.         }
  247.         if ((enc28j60Read(EIR) & EIR_TXIF)) {
  248.             //printf("EIR_TXIF set! ");
  249.         }
  250.         if ((enc28j60Read(ESTAT) & ESTAT_TXABRT)) {
  251.             //printf("ESTAT_TXABRT set!\n");
  252.             //printf("MACLCON1: %i\n", enc28j60Read(MACLCON1));
  253.             enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ESTAT, ESTAT_TXABRT);
  254.         }
  255.        
  256.         // get the next new packet:
  257.         plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
  258.  
  259.         /*plen will ne unequal to zero if there is a valid
  260.          * packet (without crc error) */
  261.         if (plen!=0){
  262.             // arp is broadcast if unknown but a host may also
  263.             // verify the mac address by sending it to
  264.             // a unicast address.
  265.             if (eth_type_is_arp_and_my_ip(buf,plen)) {
  266.                     make_arp_answer_from_request(buf);
  267.             } else {
  268.                 /* check if ip packets (icmp or udp) are for us by checking eth type and receiver ip adress: */
  269.                 if (eth_type_is_ip_and_my_ip(buf,plen)!=0) {
  270.                    
  271.                     /* a ping packet, let's send pong */
  272.                     if (buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V) {
  273.                             make_echo_reply_from_request(buf,plen);
  274.                     }
  275.                    
  276.                     /* If packet is an udp packet */
  277.                     if (buf[IP_PROTO_P]==IP_PROTO_UDP_V) {
  278.                         payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
  279.                         uint8_t i = 0;
  280.                        
  281.                         /* if port is can2serial-port (default 1100) */
  282.                         if ((buf[UDP_DST_PORT_H_P]==((locCan2SerPrt>>8) & 0xff)) && (buf[UDP_DST_PORT_L_P] == (locCan2SerPrt & 0xff))) {
  283.                             while(i<6) {
  284.                                 prgremotemac[i]=buf[ETH_SRC_MAC +i];
  285.                                 i++;
  286.                             }
  287.                             i=0;
  288.                             while(i<4) {
  289.                                 prgremoteip[i]=buf[IP_SRC_P +i];
  290.                                 i++;
  291.                             }
  292.                             gotcan2serserver = 1;
  293.                            
  294.                             /* If data is a raw can packet */
  295.                             if ((buf[UDP_DATA_P]==C2S_START_BYTE) && (buf[UDP_DATA_P+16]==C2S_END_BYTE) && (payloadlen==17))
  296.                             {
  297. #if USE_STDCAN == 0
  298.                                 Can_Message_t cm;
  299.                                 cm.DataLength = buf[UDP_DATA_P+7];
  300.                                
  301.                                 if (cm.DataLength > 8)
  302.                                 {
  303.                                     cm.DataLength = 8;
  304.                                 }
  305.                                
  306.                                 cm.RemoteFlag = buf[UDP_DATA_P+6];
  307.                                 cm.ExtendedFlag = buf[UDP_DATA_P+5];
  308.                                 cm.Id = (uint32_t)buf[UDP_DATA_P+1] + ((uint32_t)buf[UDP_DATA_P+2] << 8) +
  309.                                         ((uint32_t)buf[UDP_DATA_P+3] << 16) + ((uint32_t)buf[UDP_DATA_P+4] << 24);
  310.                                 uint8_t i;
  311.                                 for (i = 0; i < cm.DataLength; i++) {
  312.                                     cm.Data.bytes[i] = buf[UDP_DATA_P+8+i];
  313.                                 }
  314.                                 Can_Send(&cm);
  315. #else
  316.                                 static StdCan_Msg_t cm;
  317.                                 cm.Length = buf[UDP_DATA_P+7];
  318.                                
  319.                                 if (cm.Length > 8)
  320.                                 {
  321.                                     cm.Length = 8;
  322.                                 }
  323.                                
  324.                                 cm.Id = (uint32_t)buf[UDP_DATA_P+1] + ((uint32_t)buf[UDP_DATA_P+2] << 8) +
  325.                                         ((uint32_t)buf[UDP_DATA_P+3] << 16) + ((uint32_t)buf[UDP_DATA_P+4] << 24);
  326.                                 uint8_t i;
  327.                                 for (i = 0; i < cm.Length; i++) {
  328.                                     cm.Data[i] = buf[UDP_DATA_P+8+i];
  329.                                 }
  330.                                 StdCan_Put(&cm);
  331. #endif
  332.                             }
  333.                             /* of ir data is an udp ping */
  334.                             else if ((buf[UDP_DATA_P]==C2S_PING_BYTE) && (payloadlen<=2) && (payloadlen>0))
  335.                             {
  336.                                 char sendbuf3[1];
  337.                                 sendbuf3[0] = C2S_PING_BYTE;
  338.                
  339. #ifndef ENC28J60_USART_SPI_MODE
  340.                                 cli();
  341. #endif
  342.                                 send_udp(buf, sendbuf3, 1, rmCan2SerPrt, prgremotemac, prgremoteip);
  343. #ifndef ENC28J60_USART_SPI_MODE
  344.                                 sei();
  345. #endif
  346.                             }
  347.                         }
  348.                     }                      
  349.                 }
  350.             }
  351.         }
  352.     }
  353.     return 0;
  354. }
  355.  
  356.