Subversion Repositories HomeAutomation

Rev

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