Subversion Repositories HomeAutomation

Rev

Rev 693 | Rev 698 | Go to most recent revision | 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 <config.h>
  23. /* lib files */
  24. #if USE_STDCAN == 1
  25. #include <stdcan.h>
  26. #else
  27. #include <mcp2515.h>
  28. #endif
  29. #include <serial.h>
  30. #include <uart.h>
  31. #include <timebase.h>
  32.  
  33.  
  34. #if USE_STDCAN == 1
  35. #if SENDTIMESTAMP == 1
  36. #warning SENDTIMESTAMP not fully implemented with StdCan yet.
  37. #endif
  38. #endif
  39.  
  40.  
  41. /*-----------------------------------------------------------------------------
  42.  * Defines
  43.  *---------------------------------------------------------------------------*/
  44. #define UART_START_BYTE 253
  45. #define UART_END_BYTE 250
  46.  
  47. #if USE_STDCAN == 0
  48. volatile Can_Message_t rxMsg; // Message storage
  49. volatile uint8_t rxMsgFull;   // Synchronization flag
  50. #endif
  51.  
  52. const uint8_t days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  53.  
  54. union {
  55.     uint32_t packed;
  56.     struct date_t {
  57.         unsigned ss:6;
  58.         unsigned mm:6;
  59.         unsigned hh:5;
  60.         unsigned DD:5;
  61.         unsigned MM:4;
  62.         unsigned YY:6;
  63.     } unpacked;
  64. } date;
  65.  
  66. #if SENDTIMESTAMP == 1
  67. void IncTime(void) {
  68.     static uint8_t YY=07, MM=03, DD=02, hh=23, mm=58, ss=00;
  69.    
  70.     if (ss++ > 59) {
  71.         ss=0;
  72.         if (mm++ > 59) {
  73.             mm=0;
  74.             if (hh++ > 23) {
  75.                 hh=0;
  76.                 if (DD++ > days[MM-1] + ((YY%4) & (MM==2)) ? 1 : 0) {
  77.                     DD=1;
  78.                     if (MM++ > 12) {
  79.                         MM=1; YY++;
  80.                     }
  81.                 }
  82.             }
  83.         }
  84.     }
  85.     date.unpacked.YY = YY;
  86.     date.unpacked.MM = MM;
  87.     date.unpacked.DD = DD;
  88.     date.unpacked.hh = hh;
  89.     date.unpacked.mm = mm;
  90.     date.unpacked.ss = ss;
  91. }
  92. #endif
  93. /*-----------------------------------------------------------------------------
  94.  * Functions
  95.  *---------------------------------------------------------------------------*/
  96. /**
  97.  * Parses an incoming UART byte by maintaining a state machine. The UART
  98.  * bytes will build up a CAN message according to the protocol described here:
  99.  *
  100.  * http://www.arune.se/projekt/doku.php?id=homeautomation:pc-mjukvara
  101.  *
  102.  * @param c
  103.  *      The received UART byte.
  104.  */
  105. void UartParseByte(uint8_t c) {
  106. #if USE_STDCAN == 0
  107.     static Can_Message_t cm;
  108. #else
  109.     static StdCan_Msg_t cm;
  110. #endif
  111.     static uint8_t waitingMessage = 0;
  112.     static uint32_t startTime = 0;
  113.     static int8_t count = 0;
  114.    
  115.     /* 50ms timeout */
  116.     if (waitingMessage && Timebase_PassedTimeMillis(startTime) > 50) {
  117.         waitingMessage = 0;
  118.     }
  119.    
  120.     if (waitingMessage) {
  121.         /* save start time */
  122.         startTime = Timebase_CurrentTime();
  123.         /* UART END */
  124.         if (count >= 15) {
  125.             if (c == UART_END_BYTE) {
  126.                 PORTC ^= (1<<PC0);
  127. #if USE_STDCAN == 0
  128.                 Can_Send(&cm);
  129. #else
  130.                 StdCan_Put(&cm);
  131. #endif
  132.             }
  133.             waitingMessage = 0;
  134.             return;
  135.         }
  136.         /* data */
  137.         else if (count >= 7) {
  138. #if USE_STDCAN == 0
  139.             cm.Data.bytes[count-7] = c;
  140. #else
  141.             cm.Data[count-7] = c;
  142. #endif
  143.             count++;
  144.             return;
  145.         }
  146.         /* data length */
  147.         else if (count >= 6) {
  148. #if USE_STDCAN == 0
  149.             cm.DataLength = c;
  150. #else
  151.             cm.Length = c;
  152. #endif
  153.             count++;
  154.             return;
  155.         }
  156.         /* remote request flag */
  157.         else if (count >= 5) {
  158. #if USE_STDCAN == 0
  159.             cm.RemoteFlag = c;
  160. #endif
  161.             count++;
  162.             return;
  163.         }
  164.         /* extended */
  165.         else if (count >= 4) {
  166. #if USE_STDCAN == 0
  167.             cm.ExtendedFlag = c;
  168. #endif
  169.             count++;
  170.             return;
  171.         }
  172.         /* ident */
  173.         else if (count >= 0) {
  174.             cm.Id += ((uint32_t)c << (count*8));
  175.             count++;
  176.             return;
  177.         }
  178.     }
  179.    
  180.     if (c == UART_START_BYTE && !waitingMessage) {
  181.         waitingMessage = 1;
  182.         startTime = Timebase_CurrentTime();
  183.         count = 0;
  184.         cm.Id = 0;
  185.         return;
  186.     }
  187. }
  188.  
  189. #if USE_STDCAN == 0
  190. void Can_Process(Can_Message_t* msg) {
  191.     if (!(msg->ExtendedFlag)) return; // We don't care about standard CAN frames.
  192.  
  193.     if (!rxMsgFull) {
  194.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  195.         rxMsgFull = 1;
  196.     }
  197. }
  198. #endif
  199.  
  200.  
  201. /*-----------------------------------------------------------------------------
  202.  * Main Program
  203.  *---------------------------------------------------------------------------*/
  204. int main(void) {
  205. //  For calibrating internal oscillator
  206. //  OSCCAL = eeprom_read_byte(0);
  207.     Timebase_Init();
  208.     Serial_Init();
  209. #if USE_STDCAN == 0
  210.     Can_Init();
  211. #else
  212.     StdCan_Init(0);
  213. #endif 
  214.    
  215.     DDRC = 1<<PC1 | 1<<PC0;
  216.     PORTC = (1<<PC1) | (1<<PC0);
  217.    
  218.     sei();
  219.    
  220. #if SENDTIMESTAMP == 1
  221. #if USE_STDCAN == 0
  222.     Can_Message_t timeMsg;
  223. #else
  224.     StdCan_Msg_t timeMsg;
  225. #endif 
  226.     uint32_t time = Timebase_CurrentTime();
  227.     uint32_t time1 = time;
  228.     uint32_t unixtime = 0;
  229. #endif
  230.     uint16_t rxByte;
  231.     uint8_t i = 0;
  232.    
  233. #if SENDTIMESTAMP == 1
  234. #if USE_STDCAN == 0
  235.     timeMsg.ExtendedFlag = 1;
  236.     timeMsg.RemoteFlag = 0;
  237.     timeMsg.DataLength = 8;
  238. #else
  239.     /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
  240.     timeMsg.Length = 0;
  241. #endif
  242.     timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
  243.     //timeMsg.Id = 0; //Same thing, and lib's can.h is not updated.
  244. #endif
  245.    
  246. #if USE_STDCAN == 1
  247.     StdCan_Msg_t rxMsg;
  248. #endif 
  249.    
  250.     /* main loop */
  251.     while (1) {
  252.         /* any new CAN messages received? */
  253. #if USE_STDCAN == 0
  254.         if (rxMsgFull) {
  255. #else
  256.         if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) {
  257. #endif
  258.             // Toggle activity LED
  259.             PORTC ^= (1<<PC1);
  260.             /* send message to CanWatcher */
  261.             uart_putc(UART_START_BYTE);
  262.             uart_putc((uint8_t)rxMsg.Id);
  263.             uart_putc((uint8_t)(rxMsg.Id>>8));
  264.             uart_putc((uint8_t)(rxMsg.Id>>16));
  265.             uart_putc((uint8_t)(rxMsg.Id>>24));
  266. #if USE_STDCAN == 0
  267.             uart_putc(rxMsg.ExtendedFlag);
  268.             uart_putc(rxMsg.RemoteFlag);
  269.             uart_putc(rxMsg.DataLength);
  270.             for (i=0; i<8; i++) {
  271.                 uart_putc(rxMsg.Data.bytes[i]);
  272.             }
  273. #else
  274.             uart_putc(1);
  275.             uart_putc(0);
  276.             uart_putc(rxMsg.Length);
  277.             for (i=0; i<8; i++) {
  278.                 uart_putc(rxMsg.Data[i]);
  279.             }
  280. #endif
  281.             uart_putc(UART_END_BYTE);
  282.            
  283. #if USE_STDCAN == 0
  284.             rxMsgFull = 0;
  285. #endif
  286.         }
  287.        
  288.         /* any UART bytes received? */
  289.         rxByte = uart_getc();
  290.         while (rxByte != UART_NO_DATA) {
  291.             /* parse byte! */
  292.             UartParseByte((uint8_t)(rxByte & 0x00FF));
  293.             /* receive next */
  294.             rxByte = uart_getc();
  295.         }
  296.        
  297. #if SENDTIMESTAMP == 1
  298.         time1 = Timebase_CurrentTime();
  299.         if ((time1 - time) > 1000) {
  300.             time = time1;
  301. #if USE_STDCAN == 0
  302.             timeMsg.Data.dwords[0] = ++unixtime;
  303.             IncTime();
  304.             timeMsg.Data.dwords[1] = date.packed;
  305.             Can_Send(&timeMsg);
  306. #else
  307.             /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
  308.             StdCan_Put(&timeMsg);
  309. #endif
  310.         }
  311. #endif
  312.     }
  313.    
  314.     return 0;
  315. }
  316.