Subversion Repositories HomeAutomation

Rev

Rev 527 | 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/timer/timebase.h>
  9. #include <drivers/ir/receiver/irreceiver.h>
  10.  
  11. #define APP_TYPE    CAN_APPTYPES_IRRECEIVER
  12. #define APP_VERSION 0x0003
  13.  
  14. #define STATE_IDLE      0
  15. #define STATE_IR_REPEAT 1
  16.  
  17. #define IR_ID_DATA  0
  18. #define IR_ID_RAW   1
  19. #define IR_ID_DEBUG 10
  20.  
  21. // A simple message "queue", with space for one message only.
  22. // These are declared volatile to tell the compiler not to optimize away accesses.
  23. volatile Can_Message_t rxMsg; // Message storage
  24. volatile uint8_t rxMsgFull;   // Synchronization flag
  25.  
  26. // CAN message reception callback.
  27. // This function runs with interrupts disabled, keep it as short as possible.
  28. void can_receive(Can_Message_t *msg) {
  29.     if (!rxMsgFull) {
  30.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  31.         rxMsgFull = 1;
  32.     }
  33. }
  34.  
  35. int main(void)
  36. {
  37.     // Enable interrupts as early as possible
  38.     sei();
  39.    
  40.     Timebase_Init();
  41.     //Serial_Init();
  42.     IrReceive_Init();
  43.    
  44.     Can_Message_t txMsg;
  45.     txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
  46.     txMsg.DataLength = 4;
  47.     txMsg.RemoteFlag = 0;
  48.     txMsg.ExtendedFlag = 1;
  49.     txMsg.Data.words[0] = APP_TYPE;
  50.     txMsg.Data.words[1] = APP_VERSION;
  51.    
  52.     // Set up callback for CAN reception, this is optional if only sending is required.
  53.     BIOS_CanCallback = &can_receive;
  54.     // Send CAN_NMT_APP_START
  55.     BIOS_CanSend(&txMsg);
  56.  
  57.     //txMsg.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_IR << CAN_SHIFT_SNS_TYPE) | (IR_ID_DATA<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
  58.    
  59.     unsigned long time = Timebase_CurrentTime();
  60.     unsigned long irTimeoutTime = 100;
  61.    
  62.     uint8_t ir_protocol, ir_address, ir_command;
  63.     uint16_t ir_timeout;
  64.     uint8_t state = STATE_IDLE;
  65.  
  66.     while (1) {
  67.         #if 0
  68.         time = Timebase_CurrentTime();
  69.         if (state == STATE_IDLE) {
  70.             if (IrReceive_CheckIR(&ir_protocol, &ir_address, &ir_command, &ir_timeout) == IR_OK) {
  71.                 txMsg.Data.bytes[0] = 0x00;
  72.                 txMsg.Data.bytes[1] = ir_protocol;
  73.                 txMsg.Data.bytes[2] = ir_address;
  74.                 txMsg.Data.bytes[3] = ir_command;
  75.                 txMsg.DataLength = 4;
  76.                 txMsg.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_IR << CAN_SHIFT_SNS_TYPE) | (IR_ID_DATA<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
  77.                 BIOS_CanSend(&txMsg);
  78.                 irTimeoutTime = Timebase_CurrentTime();
  79.                 state = STATE_IR_REPEAT;
  80.             }
  81.         } else if (state == STATE_IR_REPEAT) {
  82.             //kolla efter ny ir, om ingen ny ir och timeout så sätt state till IDLE
  83.             if (time - irTimeoutTime >= ir_timeout) {      
  84.                 state = STATE_IDLE;
  85.                 txMsg.Data.bytes[0] = 0x0f;
  86.                 BIOS_CanSend(&txMsg);
  87.             }
  88.             if (IrReceive_CheckIdle() == IR_OK) {
  89.                 irTimeoutTime = Timebase_CurrentTime();
  90.             }
  91.         }
  92.         #endif
  93.        
  94.         #if 1
  95.         time = Timebase_CurrentTime();
  96.        
  97.         if (state == STATE_IDLE) {
  98.             /* test for irdata */
  99.             uint8_t returnval = IrReceive_CheckIR(&ir_protocol, &ir_address, &ir_command, &ir_timeout);
  100.             if (returnval == IR_OK) {
  101.                 /* a protocol was found for irdata, send on can */
  102.                 txMsg.Data.bytes[0] = 0x00;
  103.                 txMsg.Data.bytes[1] = ir_protocol;
  104.                 txMsg.Data.bytes[2] = ir_address;
  105.                 txMsg.Data.bytes[3] = ir_command;
  106.                 txMsg.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_IR << CAN_SHIFT_SNS_TYPE) | (IR_ID_DATA<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
  107.                 txMsg.DataLength = 4;
  108.                 BIOS_CanSend(&txMsg);
  109.                
  110.                 /* set up timeout */
  111.                 irTimeoutTime = Timebase_CurrentTime();
  112.                 state = STATE_IR_REPEAT;
  113.                
  114.             } else if (returnval == IR_NO_PROTOCOL) {
  115.                 /* the protocol is unknown so the raw ir-data is sent, makes it easier to develop a new protocol */
  116.                 ir_protocol = IR_PROTO_UNKNOWN;     //used in STATE_IR_REPEATE, to know if to send a release
  117.                 txMsg.DataLength = 8;
  118.                 txMsg.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_IR << CAN_SHIFT_SNS_TYPE) | (IR_ID_RAW<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
  119.                 uint8_t datacnt = getRawDataCnt();
  120.                 for (uint8_t i = 0; i < datacnt>>2; i++) {
  121.                     uint8_t index = i<<2;
  122.                     txMsg.Data.words[0] = getRawData(index);
  123.                     txMsg.Data.words[1] = getRawData(index+1);
  124.                     txMsg.Data.words[2] = getRawData(index+2);
  125.                     txMsg.Data.words[3] = getRawData(index+3);
  126.                    
  127.                     /* buffers will be filled when sending more than 2-3 messages, so retry until sent */
  128.                     //while (BIOS_CanSend(&txMsg) != CAN_OK) {}
  129.                     BIOS_CanSend(&txMsg);
  130.                    
  131.                     uint16_t dummycnt = 1;
  132.                     while (dummycnt > 0) {
  133.                         dummycnt++;
  134.                         asm("nop");
  135.                         asm("nop");
  136.                     }
  137.                 }
  138.                
  139.                 uint8_t lastpacketcnt = datacnt&0x03;
  140.                 if (lastpacketcnt > 0) {
  141.                     txMsg.DataLength = lastpacketcnt<<1;
  142.                     for (uint8_t i = 0; i < lastpacketcnt; i++) {
  143.                         txMsg.Data.words[i] = getRawData((datacnt&0xfc)|i);
  144.                     }
  145.                     /* buffers will be filled when sending more than 2-3 messages, so retry until sent */
  146.                     //while (BIOS_CanSend(&txMsg) != CAN_OK) {}
  147.                     BIOS_CanSend(&txMsg);
  148.                 }
  149.  
  150.                 irTimeoutTime = Timebase_CurrentTime();
  151.                 state = STATE_IR_REPEAT;
  152.                 ir_timeout = 200;           /* Set a default timeout */
  153.             } else if (returnval != IR_NO_DATA) {
  154.                 /* debug, send the returned message on errors (except for IR_NO_DATA-errors) */
  155.                 txMsg.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_IR << CAN_SHIFT_SNS_TYPE) | (IR_ID_DEBUG<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
  156.                 txMsg.DataLength = 1;
  157.                 txMsg.Data.bytes[0] = returnval;
  158.                 BIOS_CanSend(&txMsg);
  159.             }
  160.  
  161.         } else if (state == STATE_IR_REPEAT) {
  162.             /* check for new ir-data, if no new data during the timout-time then set state to IDLE */
  163.             if (time - irTimeoutTime >= ir_timeout) {      
  164.                 state = STATE_IDLE;
  165.                 /* if the protocol was known then send a release-message */
  166.                 if (ir_protocol != IR_PROTO_UNKNOWN) {
  167.                     txMsg.Data.bytes[0] = 0x0f;
  168.                     BIOS_CanSend(&txMsg);
  169.                 }
  170.             }
  171.             if (IrReceive_CheckIdle() == IR_OK) {
  172.                 irTimeoutTime = Timebase_CurrentTime();
  173.             }
  174.         }
  175.            
  176.         #endif
  177.  
  178.        
  179.         if (rxMsgFull) {
  180.             /* No message reception functionality implemented */
  181.            
  182.             /* Flush the received message */
  183.             rxMsgFull = 0; //  
  184.         }
  185.     }
  186.    
  187.     return 0;
  188. }
  189.