Subversion Repositories HomeAutomation

Rev

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