CROTUS / CROTUS_XBee

Dependents:   ProjetCasque

Fork of CROTUS_XBee by Valentin Libioulle

Revision:
0:2a59dd59ee5e
Child:
1:13c7d6237a53
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xbee.cpp	Mon Mar 27 15:09:52 2017 +0000
@@ -0,0 +1,307 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "xbee.h"
+
+DigitalOut _xbeeConnection(LED4);
+
+Serial _xbee(p9, p10);
+DigitalOut _xbeeRst(p8);
+
+// Hidden functions
+namespace {
+    char destination64bit[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    char destination16bit[2] = {0xff, 0xfe};
+    
+    const int HARDWARE_RESET_SIGNAL = 0x10;
+    const int CONNECTED_SIGNAL = 0x20;
+    const int TICKER_SIGNAL = 0x40;
+    const int RESPONSE_SIGNAL = 0x80;
+    
+    int responseStatus;
+    
+    int panID = 0xB00B;
+    char frameID = 0;
+    
+    Thread _xbeeReceiver;
+    Thread * _xbeeTransmitter;
+    
+    void(*_callback)(char*, int) = 0;
+
+    inline char GetFrameID(){
+        ++frameID;
+        if (frameID == 0){
+            frameID = 1;
+        }
+        return frameID;
+    }
+    
+    inline uint16_t GetFrameLength(char * buffer){
+        return (((uint16_t)buffer[LENGTH_MSB_IDX]) << 8) + buffer[LENGTH_LSB_IDX];
+    }
+    
+    bool ValidateCheckSum(char * buffer){
+        uint16_t length = GetFrameLength(buffer);
+        
+        char sum = 0;
+        for (int i = 0; i <= length; ++i){
+            sum += buffer[i + API_ID_IDX];
+        }
+        
+        return sum == 0xff;
+    }
+    
+    inline uint16_t GetAtParamLength(char * buffer){
+        return GetFrameLength(buffer) - AT_MIN_SIZE;
+    }
+    
+    inline uint16_t GetAtQueueParamLength(char * buffer){
+        return GetFrameLength(buffer) - AT_QUEUE_MIN_SIZE;
+    }
+    
+    inline uint16_t GetTransmitDataLength(char * buffer){
+        return GetFrameLength(buffer) - TRANSMIT_MIN_SIZE;
+    }
+    
+    inline uint16_t GetRemoteAtRequestParamLength(char * buffer){
+        return GetFrameLength(buffer) - REMOTE_AT_RQST_MIN_SIZE;
+    }
+    
+    inline uint16_t GetAtResponseParamLength(char * buffer){
+        return GetFrameLength(buffer) - AT_CMD_RSP_MIN_SIZE;
+    }
+    
+    inline uint16_t GetReceivedPacketDataLength(char * buffer){
+        return GetFrameLength(buffer) - RECEIVED_PACKET_MIN_SIZE;
+    }
+    
+    inline long long int Get64Addr(char * buffer, int start){
+        long long int addr = 0;
+        memcpy(&addr, &buffer[start], ADDR_64BIT_SIZE);
+        
+        return addr;
+    }
+    
+    inline short Get16Addr(char * buffer, int start){
+        short addr = 0;
+        memcpy(&addr, &buffer[start], ADDR_16BIT_SIZE);
+        
+        return addr;
+    }
+    
+    void SetCheckSum(char * buffer){
+        uint16_t length = GetFrameLength(buffer);
+        
+        char sum = 0;
+        
+        int max = length + 3;
+        
+        for(int i = 3; i < max; ++i){
+            sum += buffer[i];
+        }
+        
+        buffer[max] = 0xff - sum;
+    }
+    
+    void XBeeSend(char * buffer, int count){
+        for ( int i = 0; i < count; ++i ){
+            _xbee.putc(buffer[i]);
+            wait_us(25);
+        }
+    }
+    
+    void XBeeSendATCommand(bool queue, char * type, char * data, int dataLength){
+        char buffer[64];
+        buffer[START_IDX] = START;
+        buffer[LENGTH_MSB_IDX] = (dataLength + AT_MIN_SIZE) >> 8;
+        buffer[LENGTH_LSB_IDX] = (dataLength + AT_MIN_SIZE) & 0xff;
+        buffer[API_ID_IDX] = queue ? API_ID_AT_CMD_QUEUE : API_ID_AT_CMD;
+        buffer[FRAME_ID_IDX] = GetFrameID();
+        memcpy(&buffer[AT_CMD_ID_IDX], type, AT_CMD_ID_SIZE);
+        memcpy(&buffer[AT_PARAM_IDX], data, dataLength);
+        
+        SetCheckSum(buffer);
+        
+        while(true){
+            XBeeSend(buffer, dataLength + AT_MIN_SIZE + FRAME_MIN_SIZE);
+        
+            Thread::signal_wait(RESPONSE_SIGNAL);
+            
+            switch (responseStatus){
+            case AT_CMD_RSP_STATUS_OK:
+                return;
+            case AT_CMD_RSP_STATUS_ERROR:
+            case AT_CMD_RSP_STATUS_INVALID_CMD:
+            case AT_CMD_RSP_STATUS_INVALID_PARAM:
+            case AT_CMD_RSP_STATUS_TX_FAILURE:
+            default:
+                _xbeeConnection = 0;
+                break;
+            }
+        }
+    }
+    
+    inline void XBeeSendATID(){
+        char idBuf[8];
+        for (int i = 0; i < 8; ++i){
+            idBuf[i] = (panID >> (56 - 8 * i)) & 0xff;
+        }
+        XBeeSendATCommand(true, "ID", idBuf, 8);
+    }
+    
+    inline void XBeeSendATWR(){
+        XBeeSendATCommand(true, "WR", 0, 0);
+    }
+    
+    inline void XBeeSendATAC(){
+        XBeeSendATCommand(true, "AC", 0, 0);
+    }
+
+    inline char XbeeReadChar(){
+        while(!_xbee.readable()){
+        }
+        return _xbee.getc();
+    }
+    
+    void HandleXbeeReceivedPacket(char * cmd){
+        _callback(&cmd[RECEIVED_PACKET_DATA_IDX], GetReceivedPacketDataLength(cmd));
+    }
+    
+    void HandleXbeeModemStatus(char * cmd){
+        switch(cmd[MODEM_STATUS_STATUS_IDX]){
+        case MODEM_STATUS_HARDWARE_RST:
+            _xbeeTransmitter->signal_set(HARDWARE_RESET_SIGNAL);
+            break;
+        case MODEM_STATUS_COORDINATOR_STARTED: // For the coordinator
+        case MODEM_STATUS_JOINED_NETWORK:      // For the rooter
+            _xbeeTransmitter->signal_set(CONNECTED_SIGNAL);
+            break;
+        default:
+            _xbeeConnection = 0;
+            break;
+        }
+    }
+    
+    void HandleXBeeATCommandResponse(char * cmd){
+        responseStatus = cmd[AT_CMD_RSP_STATUS_IDX];
+        _xbeeTransmitter->signal_set(RESPONSE_SIGNAL);
+    }
+    
+    void HandleXbeeTransmitStatus(char * cmd){
+        switch(cmd[TRANSMIT_STATUS_DELIVERY_STATUS_IDX]){
+        case TRANSMIT_STATUS_OK:
+            responseStatus = cmd[TRANSMIT_STATUS_DELIVERY_STATUS_IDX];
+            _xbeeTransmitter->signal_set(RESPONSE_SIGNAL);
+            break;
+        default:
+            _xbeeConnection = 0;
+        }
+    }
+    
+    void HandleXbeeReceivedCommand(char * cmd){
+        switch(cmd[API_ID_IDX]){
+        case API_ID_AT_CMD_RSP:
+            HandleXBeeATCommandResponse(cmd);
+            break;
+        case API_ID_MODEM_STATUS:
+            HandleXbeeModemStatus(cmd);
+            break;
+        case API_ID_RECEIVED_PACKET:
+            HandleXbeeReceivedPacket(cmd);
+            break;
+        case API_ID_TRANSMIT_STATUS:
+            HandleXbeeTransmitStatus(cmd);
+            break;
+        default:
+            _xbeeConnection = 0;
+            break;
+        }
+    }
+    
+    void _XbeeReceiver(){
+        char buffer[64];
+        while(true){
+            buffer[START_IDX] = XbeeReadChar();
+            if (buffer[START_IDX] != START){
+                _xbeeConnection = 0;
+                continue;
+            }
+            buffer[LENGTH_MSB_IDX] = XbeeReadChar();
+            buffer[LENGTH_LSB_IDX] = XbeeReadChar();
+            int length = GetFrameLength(buffer);
+            
+            for (int i = 0; i <= length; ++i){
+                buffer[i + API_ID_IDX] = XbeeReadChar();
+            }
+            if (!ValidateCheckSum(buffer)){
+                _xbeeConnection = 0;
+                continue;
+            }
+            
+            HandleXbeeReceivedCommand(buffer);
+        }
+    }
+
+};
+
+/*******************************************************/
+/**********************XBEE SEND************************/
+/*******************************************************/
+
+void XBeeSendData(char * data, int dataLength){
+    char buffer[64];
+    buffer[START_IDX] = START;
+    buffer[LENGTH_MSB_IDX] = (dataLength + TRANSMIT_MIN_SIZE) >> 8;
+    buffer[LENGTH_LSB_IDX] = (dataLength + TRANSMIT_MIN_SIZE) & 0xff;
+    buffer[API_ID_IDX] = API_ID_TRANSMIT;
+    buffer[FRAME_ID_IDX] = GetFrameID();
+    memcpy(&buffer[TRANSMIT_64BIT_MSB_IDX], destination64bit, ADDR_64BIT_SIZE);
+    memcpy(&buffer[TRANSMIT_16BIT_MSB_IDX], destination16bit, ADDR_16BIT_SIZE);
+    buffer[TRANSMIT_BROADCAST_IDX] = TRANSMIT_DEFAULT_BROADCAST;
+    buffer[TRANSMIT_OPT_IDX] = TRANSMIT_DEFAULT_OPT;
+    memcpy(&buffer[TRANSMIT_DATA_IDX], data, dataLength);
+    
+    SetCheckSum(buffer);
+    
+    while(true) {
+        XBeeSend(buffer, dataLength + TRANSMIT_MIN_SIZE + FRAME_MIN_SIZE);
+    
+        Thread::signal_wait(RESPONSE_SIGNAL);
+        
+        switch (responseStatus){
+        case TRANSMIT_STATUS_OK:
+            return;
+        default:
+            _xbeeConnection = 0;
+            break;
+        }
+    }
+}
+
+bool InitXBee(bool coordinator, void(*packetReceivedCallback)(char*, int), Thread * xbeeTransmitter){
+    _callback = packetReceivedCallback;
+    _xbeeTransmitter = xbeeTransmitter;
+    
+    if (coordinator)
+    {
+        uint8_t temp[8] = {0x00, 0x13, 0xA2, 0x00, 0x40, 0x33, 0x19, 0x8D};
+        memcpy(destination64bit, temp, 8);
+    }
+    
+    _xbeeReceiver.start(callback(_XbeeReceiver));
+    
+    _xbeeRst.write(0);
+    wait(0.4);
+    _xbeeRst.write(1);
+    
+    Thread::signal_wait(HARDWARE_RESET_SIGNAL);
+    
+    XBeeSendATID();
+    XBeeSendATWR();
+    XBeeSendATAC();
+    
+    Thread::signal_wait(CONNECTED_SIGNAL);
+    
+    _xbeeConnection = 1;
+    
+    return true;
+}