Subversion Repositories HomeAutomation

Rev

Rev 149 | Blame | 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
  7.  *  
  8.  */
  9.  
  10. /*-----------------------------------------------------------------------------
  11.  * Includes
  12.  *---------------------------------------------------------------------------*/
  13. /* system files */
  14. #include <avr/io.h>
  15. #include <avr/interrupt.h>
  16. #include <avr/wdt.h>
  17. #include <avr/eeprom.h>
  18. #include <stdio.h>
  19. /* lib files */
  20. #include <can.h>
  21. #include <serial.h>
  22. #include <uart.h>
  23. #include <timebase.h>
  24.  
  25.  
  26. /*-----------------------------------------------------------------------------
  27.  * Defines
  28.  *---------------------------------------------------------------------------*/
  29. #define UART_START_BYTE 253
  30. #define UART_END_BYTE 250
  31.  
  32. const uint8_t days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  33.  
  34. union {
  35.     uint32_t packed;
  36.     struct date_t {
  37.         unsigned ss:6;
  38.         unsigned mm:6;
  39.         unsigned hh:5;
  40.         unsigned DD:5;
  41.         unsigned MM:4;
  42.         unsigned YY:6;
  43.     } unpacked;
  44. } date;
  45.  
  46. void IncTime(void) {
  47.     static uint8_t YY=07, MM=03, DD=02, hh=23, mm=58, ss=00;
  48.    
  49.     if (ss++ > 59) {
  50.         ss=0;
  51.         if (mm++ > 59) {
  52.             mm=0;
  53.             if (hh++ > 23) {
  54.                 hh=0;
  55.                 if (DD++ > days[MM-1] + ((YY%4) & (MM==2)) ? 1 : 0))) {
  56.                     DD=1;
  57.                     if (MM++ > 12) {
  58.                         MM=1; YY++;
  59.                     }
  60.                 }
  61.             }
  62.         }
  63.     }
  64.     date.unpacked.YY = YY;
  65.     date.unpacked.MM = MM;
  66.     date.unpacked.DD = DD;
  67.     date.unpacked.hh = hh;
  68.     date.unpacked.mm = mm;
  69.     date.unpacked.ss = ss;
  70. }
  71. /*-----------------------------------------------------------------------------
  72.  * Functions
  73.  *---------------------------------------------------------------------------*/
  74. /**
  75.  * Parses an incoming UART byte by maintaining a state machine. The UART
  76.  * bytes will build up a CAN message according to the protocol described here:
  77.  *
  78.  * http://www.arune.se/projekt/doku.php?id=homeautomation:pc-mjukvara
  79.  *
  80.  * @param c
  81.  *      The received UART byte.
  82.  */
  83. void UartParseByte(uint8_t c) {
  84.     static Can_Message_t cm;
  85.     static uint8_t waitingMessage = 0;
  86.     static uint32_t startTime = 0;
  87.     static int8_t count = 0;
  88.    
  89.     /* 50ms timeout */
  90.     if (waitingMessage && Timebase_PassedTimeMillis(startTime) > 50) {
  91.         waitingMessage = 0;
  92.     }
  93.    
  94.     if (waitingMessage) {
  95.         /* save start time */
  96.         startTime = Timebase_CurrentTime();
  97.         /* UART END */
  98.         if (count >= 15) {
  99.             if (c == UART_END_BYTE) {
  100.                 PORTC ^= (1<<PC0);
  101.                 Can_Send(&cm);
  102.             }
  103.             waitingMessage = 0;
  104.             return;
  105.         }
  106.         /* data */
  107.         else if (count >= 7) {
  108.             cm.Data.bytes[count-7] = c;
  109.             count++;
  110.             return;
  111.         }
  112.         /* data length */
  113.         else if (count >= 6) {
  114.             cm.DataLength = c;
  115.             count++;
  116.             return;
  117.         }
  118.         /* remote request flag */
  119.         else if (count >= 5) {
  120.             cm.RemoteFlag = c;
  121.             count++;
  122.             return;
  123.         }
  124.         /* extended */
  125.         else if (count >= 4) {
  126.             cm.ExtendedFlag = c;
  127.             count++;
  128.             return;
  129.         }
  130.         /* ident */
  131.         else if (count >= 0) {
  132.             cm.Id += ((uint32_t)c << (count*8));
  133.             count++;
  134.             return;
  135.         }
  136.     }
  137.    
  138.     if (c == UART_START_BYTE && !waitingMessage) {
  139.         waitingMessage = 1;
  140.         startTime = Timebase_CurrentTime();
  141.         count = 0;
  142.         cm.Id = 0;
  143.         return;
  144.     }
  145. }
  146.  
  147.  
  148. /*-----------------------------------------------------------------------------
  149.  * Main Program
  150.  *---------------------------------------------------------------------------*/
  151. int main(void) {
  152.     OSCCAL = eeprom_read_byte(0);
  153.     Timebase_Init();
  154.     Serial_Init();
  155.     Can_Init();
  156.    
  157.     DDRC = 1<<PC1 | 1<<PC0;
  158.     PORTC = (1<<PC1) | (1<<PC0);
  159.    
  160.     sei();
  161.    
  162.     Can_Message_t rxMsg;
  163.     Can_Message_t timeMsg;
  164.     uint32_t time = Timebase_CurrentTime();
  165.     uint32_t time1 = time;
  166.     uint32_t unixtime = 0;
  167.     uint16_t rxByte;
  168.     uint8_t i = 0;
  169.    
  170.     timeMsg.ExtendedFlag = 1;
  171.     timeMsg.RemoteFlag = 0;
  172.     //timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE);
  173.     timeMsg.Id = 0; //Same thing, and lib's can.h is not updated.
  174.     timeMsg.DataLength = 8;
  175.    
  176.     /* main loop */
  177.     while (1) {
  178.         /* service the CAN routines */
  179.         Can_Service();
  180.        
  181.         /* any new CAN messages received? */
  182.         if (Can_Receive(&rxMsg) == CAN_OK) {
  183.             PORTC ^= (1<<PC1);
  184.             /* send message to CanWatcher */
  185.             uart_putc(UART_START_BYTE);
  186.             uart_putc((uint8_t)rxMsg.Id);
  187.             uart_putc((uint8_t)(rxMsg.Id>>8));
  188.             uart_putc((uint8_t)(rxMsg.Id>>16));
  189.             uart_putc((uint8_t)(rxMsg.Id>>24));
  190.             uart_putc(rxMsg.ExtendedFlag);
  191.             uart_putc(rxMsg.RemoteFlag);
  192.             uart_putc(rxMsg.DataLength);
  193.             for (i=0; i<8; i++) {
  194.                 uart_putc(rxMsg.Data.bytes[i]);
  195.             }
  196.             uart_putc(UART_END_BYTE);
  197.         }
  198.        
  199.         /* any UART bytes received? */
  200.         rxByte = uart_getc();
  201.         while (rxByte != UART_NO_DATA) {
  202.             /* parse byte! */
  203.             UartParseByte((uint8_t)(rxByte & 0x00FF));
  204.             /* receive next */
  205.             rxByte = uart_getc();
  206.         }
  207.        
  208.         time1 = Timebase_CurrentTime();
  209.         if ((time1 - time) > 1000) {
  210.             time = time1;
  211.             timeMsg.Data.dwords[0] = ++unixtime;
  212.             IncTime();
  213.             timeMsg.Data.dwords[1] = date.packed;
  214.             Can_Send(&timeMsg);
  215.         }
  216.     }
  217.    
  218.     return 0;
  219. }
  220.