Subversion Repositories HomeAutomation

Rev

Rev 1210 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. #include <inttypes.h>
  2. #include <avr/interrupt.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <config.h> // All configuration parameters
  6. #include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
  7. #include <drivers/uart/serial.h>
  8. #include <drivers/uart/uart.h>
  9. #include <drivers/timer/timer.h>
  10. #include <drivers/timer/timebase.h>
  11. #include <drivers/can/can.h>
  12. #include <drivers/can/mcp2515/mcp2515.h>
  13.  
  14. #define APP_TYPE    CAN_APPTYPES_SERIALTRANSCEIVER
  15. #define APP_VERSION 0x0001
  16.  
  17. //Note: Erik Calissendorff, 2009-03-29
  18. //Not sure how this is supposed to be used in the CAN message but it's part of the SNS id
  19. #define SERIAL_ID_DATA  0
  20.  
  21. //What is the maximum time  that we will wait for addition data from the serial port
  22. //before we send it in a package, the minimum time if data is available is max-1
  23. #define RECEIVE_WAIT_TIME_MS 5
  24.  
  25. // A simple message "queue", with space for one message only.
  26. // These are declared volatile to tell the compiler not to optimize away accesses.
  27. volatile Can_Message_t rxMsg; // Message storage
  28. volatile uint8_t rxMsgFull;   // Synchronization flag
  29.  
  30. // CAN message reception callback.
  31. // This function runs with interrupts disabled, keep it as short as possible.
  32. void can_receive(Can_Message_t *msg) {
  33.     if (!rxMsgFull) {
  34.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  35.         rxMsgFull = 1;
  36.     }
  37. }
  38.  
  39. int main(void)
  40. {
  41.     // Enable interrupts as early as possible
  42.     sei();
  43.  
  44.     Timebase_Init();
  45.     Serial_Init();
  46.  
  47.     Can_Message_t txMsg; // Message storage
  48.  
  49.     txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) |
  50.         (NODE_ID << CAN_SHIFT_NMT_SID);
  51.     txMsg.DataLength = 4;
  52.     txMsg.RemoteFlag = 0;
  53.     txMsg.ExtendedFlag = 1;
  54.     txMsg.Data.words[0] = APP_TYPE;
  55.     txMsg.Data.words[1] = APP_VERSION;
  56.  
  57.     // Set up callback for CAN reception, this is optional if only sending is required.
  58.     BIOS_CanCallback = &can_receive;
  59.  
  60.     // Send CAN_NMT_APP_START for the transceiver
  61.     BIOS_CanSend(&txMsg);
  62.  
  63.     //Buffer for incoming serial data
  64.     uint8_t rxBuffer[SERIAL_RX_BUFFER_SIZE];
  65.  
  66.     //Ensure that we don't try to buffer more than the buffer size
  67.     uint8_t maxReceiveData=8>SERIAL_RX_BUFFER_SIZE?SERIAL_RX_BUFFER_SIZE:8;
  68.  
  69.     //For loop variable
  70.     uint8_t i;
  71.  
  72.     //How many bytes have been received from the serial port
  73.     uint8_t received_size=0;
  74.  
  75.     //The last received data from the serial port
  76.     unsigned int received_data;
  77.  
  78.     //Used to allow multiple bytes to be send in the same package
  79.     uint32_t time = Timebase_CurrentTime();
  80.  
  81.     //Check if we got some data from the serial port
  82.     uint8_t got_received_data=0;
  83.  
  84.     while (1) {
  85.  
  86.         if (rxMsgFull) {
  87.             if ( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_ACT && ((uint16_t)((rxMsg.Id & CAN_MASK_ACT_TYPE) >> CAN_SHIFT_ACT_TYPE) == ACT_TYPE_SERIAL)) {
  88.                 //Unused uint8_t actid = (uint8_t)((rxMsg.Id & CAN_MASK_ACT_ID) >> CAN_SHIFT_ACT_ID);
  89.  
  90.                 for(i=0;i<rxMsg.DataLength;i++)
  91.                 {
  92.                     uart_putc(rxMsg.Data.bytes[i]);
  93.                 }
  94.             }
  95.  
  96.             // Flush the received message
  97.             rxMsgFull = 0; //
  98.         }
  99.  
  100.         //Receiver
  101.  
  102.         //Timer for how long we will wait for for more data before sending our packages
  103.         time = Timebase_CurrentTime();
  104.  
  105.         //We don't like to wait for the time out unless we get some data.
  106.         got_received_data=0;
  107.         do
  108.         {
  109.             received_data=uart_getc();
  110.             if(received_data != UART_NO_DATA)
  111.             {
  112.                 got_received_data=1;
  113.                 //TODO: Erik Calissendorff, 2009-03-29
  114.                 //Error handling should be added to inform us of problems with the serial link
  115.  
  116.                 rxBuffer[received_size++]=(uint8_t)(received_data & 0x00ff);
  117.             }
  118.         } while(received_size<maxReceiveData && got_received_data==1 && Timebase_CurrentTime()-time < RECEIVE_WAIT_TIME_MS);
  119.  
  120.         if(received_size > 0)
  121.         {
  122.             //TODO: Erik Calissendorff, 2009-03-29
  123.             //We like to be able to accept more then one CAN package of data at a time
  124.  
  125.             txMsg.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_SERIAL << CAN_SHIFT_SNS_TYPE) | (SERIAL_ID_DATA<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
  126.             for(i=0;i<received_size;i++)
  127.             {
  128.                 txMsg.Data.bytes[i]=rxBuffer[i];
  129.             }
  130.             txMsg.DataLength = received_size;
  131.  
  132.             BIOS_CanSend(&txMsg);
  133.         }
  134.         //Ensure we are reseting the counter
  135.         received_size=0;
  136.     }
  137.     return 0;
  138. }
  139.  
  140.