Subversion Repositories HomeAutomation

Rev

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

  1. /**
  2.  * CAN test program.
  3.  *
  4.  * @target  AVR
  5.  * @date    2006-10-29
  6.  * @author  Jimmy Myhrman, Andreas Fritiofsson
  7.  *  
  8.  */
  9.  
  10. /*-----------------------------------------------------------------------------
  11.  * Includes
  12.  *---------------------------------------------------------------------------*/
  13.  
  14. /* system files */
  15. #include <avr/io.h>
  16. #include <avr/interrupt.h>
  17. #include <avr/wdt.h>
  18. #include <avr/eeprom.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21.  
  22. #include <canid.h>
  23. #include <config.h>
  24. /* lib files */
  25. #if USE_STDCAN == 1
  26. #include <stdcan.h>
  27. #else
  28. #include <mcp2515.h>
  29. #endif
  30. #include <serial.h>
  31. #include <uart.h>
  32. #include <timebase.h>
  33.  
  34.  
  35. #if USE_STDCAN == 1
  36. #if SENDTIMESTAMP == 1
  37. #warning SENDTIMESTAMP not fully implemented with StdCan yet.
  38. #endif
  39. #endif
  40.  
  41.  
  42. /*-----------------------------------------------------------------------------
  43.  * Defines
  44.  *---------------------------------------------------------------------------*/
  45. #define UART_START_BYTE 253
  46. #define UART_END_BYTE 250
  47.  
  48. #if USE_STDCAN == 0
  49. volatile Can_Message_t rxMsg; // Message storage
  50. volatile uint8_t rxMsgFull;   // Synchronization flag
  51. #endif
  52.  
  53. const uint8_t days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  54.  
  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.  
  67. #if SENDTIMESTAMP == 1
  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;
  77.                 if (DD++ > days[MM-1] + ((YY%4) & (MM==2)) ? 1 : 0) {
  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. }
  93. #endif
  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) {
  107. #if USE_STDCAN == 0
  108.     static Can_Message_t cm;
  109. #else
  110.     static StdCan_Msg_t cm;
  111. #endif
  112.     static uint8_t waitingMessage = 0;
  113.     static uint32_t startTime = 0;
  114.     static int8_t count = 0;
  115.    
  116.     /* 50ms timeout */
  117.     if (waitingMessage && Timebase_PassedTimeMillis(startTime) > 50) {
  118.         waitingMessage = 0;
  119.     }
  120.    
  121.     if (waitingMessage) {
  122.         /* save start time */
  123.         startTime = Timebase_CurrentTime();
  124.         /* UART END */
  125.         if (count >= 15) {
  126.             if (c == UART_END_BYTE) {
  127.                 PORTC ^= (1<<PC0);
  128. #if USE_STDCAN == 0
  129.                 Can_Send(&cm);
  130. #else
  131.                 StdCan_Put(&cm);
  132. #endif
  133.             }
  134.             waitingMessage = 0;
  135.             return;
  136.         }
  137.         /* data */
  138.         else if (count >= 7) {
  139. #if USE_STDCAN == 0
  140.             cm.Data.bytes[count-7] = c;
  141. #else
  142.             cm.Data[count-7] = c;
  143. #endif
  144.             count++;
  145.             return;
  146.         }
  147.         /* data length */
  148.         else if (count >= 6) {
  149. #if USE_STDCAN == 0
  150.             cm.DataLength = c;
  151. #else
  152.             cm.Length = c;
  153. #endif
  154.             count++;
  155.             return;
  156.         }
  157.         /* remote request flag */
  158.         else if (count >= 5) {
  159. #if USE_STDCAN == 0
  160.             cm.RemoteFlag = c;
  161. #endif
  162.             count++;
  163.             return;
  164.         }
  165.         /* extended */
  166.         else if (count >= 4) {
  167. #if USE_STDCAN == 0
  168.             cm.ExtendedFlag = c;
  169. #endif
  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;
  183.         startTime = Timebase_CurrentTime();
  184.         count = 0;
  185.         cm.Id = 0;
  186.         return;
  187.     }
  188. }
  189.  
  190. #if USE_STDCAN == 0
  191. void Can_Process(Can_Message_t* msg) {
  192.     if (!(msg->ExtendedFlag)) return; // We don't care about standard CAN frames.
  193.  
  194.     if (!rxMsgFull) {
  195.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  196.         rxMsgFull = 1;
  197.     }
  198. }
  199. #endif
  200.  
  201.  
  202. /*-----------------------------------------------------------------------------
  203.  * Main Program
  204.  *---------------------------------------------------------------------------*/
  205. int main(void) {
  206. //  For calibrating internal oscillator
  207. //  OSCCAL = eeprom_read_byte(0);
  208.     Timebase_Init();
  209.     Serial_Init();
  210. #if USE_STDCAN == 0
  211.     Can_Init();
  212. #else
  213.     StdCan_Init(0);
  214. #endif 
  215.    
  216.     DDRC = 1<<PC1 | 1<<PC0;
  217.     PORTC = (1<<PC1) | (1<<PC0);
  218.    
  219.     sei();
  220.    
  221. #if SENDTIMESTAMP == 1
  222. #if USE_STDCAN == 0
  223.     Can_Message_t timeMsg;
  224. #else
  225.     StdCan_Msg_t timeMsg;
  226. #endif 
  227.     uint32_t time = Timebase_CurrentTime();
  228.     uint32_t time1 = time;
  229.     uint32_t unixtime = 0;
  230. #endif
  231.     uint16_t rxByte;
  232.     uint8_t i = 0;
  233.    
  234. #if SENDTIMESTAMP == 1
  235. #if USE_STDCAN == 0
  236.     timeMsg.ExtendedFlag = 1;
  237.     timeMsg.RemoteFlag = 0;
  238.     timeMsg.DataLength = 8;
  239. #else
  240.     /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
  241.     timeMsg.Length = 0;
  242. #endif
  243.     timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
  244.     //timeMsg.Id = 0; //Same thing, and lib's can.h is not updated.
  245. #endif
  246.    
  247. #if USE_STDCAN == 1
  248.     StdCan_Msg_t rxMsg;
  249. #endif 
  250.    
  251.     /* main loop */
  252.     while (1) {
  253.         /* any new CAN messages received? */
  254. #if USE_STDCAN == 0
  255.         if (rxMsgFull) {
  256. #else
  257.         if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) {
  258. #endif
  259.             // Toggle activity LED
  260.             PORTC ^= (1<<PC1);
  261.             /* send message to CanWatcher */
  262.             uart_putc(UART_START_BYTE);
  263.             uart_putc((uint8_t)rxMsg.Id);
  264.             uart_putc((uint8_t)(rxMsg.Id>>8));
  265.             uart_putc((uint8_t)(rxMsg.Id>>16));
  266.             uart_putc((uint8_t)(rxMsg.Id>>24));
  267. #if USE_STDCAN == 0
  268.             uart_putc(rxMsg.ExtendedFlag);
  269.             uart_putc(rxMsg.RemoteFlag);
  270.             uart_putc(rxMsg.DataLength);
  271.             for (i=0; i<8; i++) {
  272.                 uart_putc(rxMsg.Data.bytes[i]);
  273.             }
  274. #else
  275.             uart_putc(1);
  276.             uart_putc(0);
  277.             uart_putc(rxMsg.Length);
  278.             for (i=0; i<8; i++) {
  279.                 uart_putc(rxMsg.Data[i]);
  280.             }
  281. #endif
  282.             uart_putc(UART_END_BYTE);
  283.            
  284. #if USE_STDCAN == 0
  285.             rxMsgFull = 0;
  286. #endif
  287.         }
  288.        
  289.         /* any UART bytes received? */
  290.         rxByte = uart_getc();
  291.         while (rxByte != UART_NO_DATA) {
  292.             /* parse byte! */
  293.             UartParseByte((uint8_t)(rxByte & 0x00FF));
  294.             /* receive next */
  295.             rxByte = uart_getc();
  296.         }
  297.        
  298. #if SENDTIMESTAMP == 1
  299.         time1 = Timebase_CurrentTime();
  300.         if ((time1 - time) > 1000) {
  301.             time = time1;
  302. #if USE_STDCAN == 0
  303.             timeMsg.Data.dwords[0] = ++unixtime;
  304.             IncTime();
  305.             timeMsg.Data.dwords[1] = date.packed;
  306.             Can_Send(&timeMsg);
  307. #else
  308.             /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
  309.             StdCan_Put(&timeMsg);
  310. #endif
  311.         }
  312. #endif
  313.     }
  314.    
  315.     return 0;
  316. }
  317.