Subversion Repositories HomeAutomation

Rev

Rev 765 | 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.  
  211. #if MCP_CS_BIT != PB2
  212.     /* If slave select is not set as output it might change SPI hw to slave
  213.      * See ch 18.3.2 (18.3 SS Pin Functionality) in ATmega48/88/168-datasheet */
  214.     DDRB |= (1<<PB2);
  215. #endif
  216. #if USE_STDCAN == 0
  217.     Can_Init();
  218. #else
  219.     StdCan_Init(0);
  220. #endif 
  221.    
  222.     DDRC |= 1<<PC1 | 1<<PC0;
  223.     PORTC |= (1<<PC1) | (1<<PC0);
  224.    
  225.     sei();
  226.    
  227. #if SENDTIMESTAMP == 1
  228. #if USE_STDCAN == 0
  229.     Can_Message_t timeMsg;
  230. #else
  231.     StdCan_Msg_t timeMsg;
  232. #endif 
  233.     uint32_t time = Timebase_CurrentTime();
  234.     uint32_t time1 = time;
  235.     uint32_t unixtime = 0;
  236. #endif
  237.     uint16_t rxByte;
  238.     uint8_t i = 0;
  239.    
  240. #if SENDTIMESTAMP == 1
  241. #if USE_STDCAN == 0
  242.     timeMsg.ExtendedFlag = 1;
  243.     timeMsg.RemoteFlag = 0;
  244.     timeMsg.DataLength = 8;
  245. #else
  246.     /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
  247.     timeMsg.Length = 0;
  248. #endif
  249.     timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
  250.     //timeMsg.Id = 0; //Same thing, and lib's can.h is not updated.
  251. #endif
  252.    
  253. #if USE_STDCAN == 1
  254.     StdCan_Msg_t rxMsg;
  255. #endif 
  256.    
  257.     /* main loop */
  258.     while (1) {
  259.         /* any new CAN messages received? */
  260. #if USE_STDCAN == 0
  261.         if (rxMsgFull) {
  262. #else
  263.         if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) {
  264. #endif
  265.             // Toggle activity LED
  266.             PORTC ^= (1<<PC1);
  267.             /* send message to CanWatcher */
  268.             uart_putc(UART_START_BYTE);
  269.             uart_putc((uint8_t)rxMsg.Id);
  270.             uart_putc((uint8_t)(rxMsg.Id>>8));
  271.             uart_putc((uint8_t)(rxMsg.Id>>16));
  272.             uart_putc((uint8_t)(rxMsg.Id>>24));
  273. #if USE_STDCAN == 0
  274.             uart_putc(rxMsg.ExtendedFlag);
  275.             uart_putc(rxMsg.RemoteFlag);
  276.             uart_putc(rxMsg.DataLength);
  277.             for (i=0; i<8; i++) {
  278.                 uart_putc(rxMsg.Data.bytes[i]);
  279.             }
  280. #else
  281.             uart_putc(1);
  282.             uart_putc(0);
  283.             uart_putc(rxMsg.Length);
  284.             for (i=0; i<8; i++) {
  285.                 uart_putc(rxMsg.Data[i]);
  286.             }
  287. #endif
  288.             uart_putc(UART_END_BYTE);
  289.            
  290. #if USE_STDCAN == 0
  291.             rxMsgFull = 0;
  292. #endif
  293.         }
  294.        
  295.         /* any UART bytes received? */
  296.         rxByte = uart_getc();
  297.         while (rxByte != UART_NO_DATA) {
  298.             /* parse byte! */
  299.             UartParseByte((uint8_t)(rxByte & 0x00FF));
  300.             /* receive next */
  301.             rxByte = uart_getc();
  302.         }
  303.        
  304. #if SENDTIMESTAMP == 1
  305.         time1 = Timebase_CurrentTime();
  306.         if ((time1 - time) > 1000) {
  307.             time = time1;
  308. #if USE_STDCAN == 0
  309.             timeMsg.Data.dwords[0] = ++unixtime;
  310.             IncTime();
  311.             timeMsg.Data.dwords[1] = date.packed;
  312.             Can_Send(&timeMsg);
  313. #else
  314.             /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */
  315.             StdCan_Put(&timeMsg);
  316. #endif
  317.         }
  318. #endif
  319.     }
  320.    
  321.     return 0;
  322. }
  323.