Subversion Repositories HomeAutomation

Rev

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