Code APP3

Dependencies:   mbed EthernetInterface WebSocketClient mbed-rtos BufferedSerial

Fork of APP3_Lab by Jean-Philippe Fournier

xbee.cpp

Committer:
Cheroukee
Date:
2017-10-01
Revision:
15:c4d17caf0709
Parent:
14:cd488eba8bba
Child:
17:8abdbfa6019c

File content as of revision 15:c4d17caf0709:


/***
*   xbee.cpp - en-tete de lib xbee - fouj1807 - mcgj2701
*/

#include "xbee.h"

DigitalOut xbee_transmit_led(LED1);
DigitalOut xbee_receive_led(LED2);
DigitalOut xbee_reset(p8);

Serial xbee(p13, p14); // tx, rx

char TransmitBuffer[2048] = {0};
char ReceiveBuffer[2048] = {0};

void xbee_init()
{
    xbee_receive_led = 0;
    
    wait_ms(400);
    
    xbee_reset = 1;
    
    wait_ms(5000);    
    
    //xbee_receive_led = 1;    
}

void build_api_frame_header(int frame_data_size)
{
    // Delimiter
    TransmitBuffer[FRAME_DELIMITER_POS] = ZIGBEE_DELIMITER;
    TransmitBuffer[FRAME_LEN_MSB_POS] = frame_data_size >> 8;
    TransmitBuffer[FRAME_LEN_LSB_POS] = frame_data_size & 0xFF;
}

void build_api_frame_checksum(int frame_data_size)
{
    // Calculate checksum
    char checksum = 0xFF;
    for (int i = 3; i < FRAME_CHEKSUM_POS; i++)
    {
        checksum -= TransmitBuffer[i];
    }
    
    // Insert checksum into buffer
    TransmitBuffer[FRAME_CHEKSUM_POS] = checksum;
}

void set_api_frame_type(frame_type_t frame_type)
{
    TransmitBuffer[API_FRAME_TYPE_POS] = frame_type;
}

void set_api_frame_id(int id)
{
    TransmitBuffer[API_FRAME_ID_POS] = id;
}

void set_at_command(int at_command)
{
// NOT IMPLEMENTED
}

void set_64_addr(zigbee_addr_64_t address)
{
    int i = 0;
    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_0;
    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_1;
    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_2;
    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_3;

    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_4;
    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_5;
    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_6;
    TransmitBuffer[TRANSMIT_REQ_ADDR64_MSB_POS + i++] = address.addr_7;
}

void set_16_addr(zigbee_addr_16_t address)
{
    TransmitBuffer[TRANSMIT_REQ_ADDR16_MSB_POS]         = address.addr_msb;
    TransmitBuffer[TRANSMIT_REQ_ADDR16_MSB_POS + 1]     = address.addr_lsb;
}

void set_broadcast_radius(int position, char radius)
{
    TransmitBuffer[position] = radius;
}

void set_transmit_request_options(int position, char options)
{
    TransmitBuffer[position] = options;
}

void set_transmit_data(int start_pos, char* data, int data_length)
{
    for (int i = 0; i < data_length; i++)
    {
        TransmitBuffer[start_pos + i] = data[i];
    }
}

bool transmit_request_64(char* buffer, int data_length, char options, zigbee_addr_64_t destination)
{
    build_api_frame_header(data_length + TRANSMIT_REQ_OVERHEAD_LENGTH);

    set_api_frame_type(TransmitRequest);
    set_api_frame_id(0x01);

    set_64_addr(destination);
    DECLARE_ADDR16_UNKNOWN_OR_BCAST
    set_16_addr(USE_ADDR16_UNKNOWN_OR_BCAST);

    set_broadcast_radius(15, 0);
    set_transmit_request_options(15, 0);

    set_transmit_data(TRANSMIT_REQ_DATA_START, buffer, data_length);

    build_api_frame_checksum(data_length + TRANSMIT_REQ_OVERHEAD_LENGTH);

    transmit(data_length);
    
    return false;
}

bool transmit_request_16(char* buffer, int data_length, char options, zigbee_addr_16_t destination)
{
    build_api_frame_header(data_length + TRANSMIT_REQ_OVERHEAD_LENGTH);

    set_api_frame_type(TransmitRequest);
    set_api_frame_id(0x01);
    
    DECLARE_ADDR64_BCAST
    set_64_addr(USE_ADDR64_BCAST);
    set_16_addr(destination);

    set_broadcast_radius(15, 0);
    set_transmit_request_options(15, 0);

    set_transmit_data(TRANSMIT_REQ_DATA_START, buffer, data_length);

    build_api_frame_checksum(data_length + TRANSMIT_REQ_OVERHEAD_LENGTH);
    
    transmit(data_length);

    return false;
}

bool transmit_request(char* buffer, int data_length, char options, zigbee_addr_64_t destination64, zigbee_addr_16_t destination16)
{
    build_api_frame_header(data_length + TRANSMIT_REQ_OVERHEAD_LENGTH);
    
    set_api_frame_type(TransmitRequest);
    set_api_frame_id(0x01);

    set_64_addr(destination64);
    set_16_addr(destination16);

    set_broadcast_radius(15, 0);
    set_transmit_request_options(15, 0);

    set_transmit_data(TRANSMIT_REQ_DATA_START, buffer, data_length);

    build_api_frame_checksum(data_length + TRANSMIT_REQ_OVERHEAD_LENGTH);

    transmit(data_length + TRANSMIT_REQ_OVERHEAD_LENGTH);

    return false;
}

void remote_at_command_query(char msb, char lsb, char options)
{
    char remote_command[2] = {msb, lsb};
    
    build_api_frame_header(2 + REMOTE_AT_OVERHEAD_LENGTH);

    set_api_frame_type(RemoteCommandRequest);
    set_api_frame_id(0x01);

    DECLARE_ADDR16_UNKNOWN_OR_BCAST
    DECLARE_ADDR64_BCAST

    set_64_addr(USE_ADDR64_BCAST);
    set_16_addr(USE_ADDR16_UNKNOWN_OR_BCAST);

    // Set as apply
    set_transmit_request_options(15, options);

    set_transmit_data(16, remote_command, 2);
    
    build_api_frame_checksum(2 + REMOTE_AT_OVERHEAD_LENGTH);    

    transmit(2 + REMOTE_AT_OVERHEAD_LENGTH); 
}

void remote_at_command_set(char msb, char lsb, char parameter, char options)
{
    char remote_command[3] = {msb, lsb, parameter};

    build_api_frame_header(3 + REMOTE_AT_OVERHEAD_LENGTH);

    set_api_frame_type(RemoteCommandRequest);
    set_api_frame_id(0x01);

    DECLARE_ADDR16_UNKNOWN_OR_BCAST
    DECLARE_ADDR64_BCAST

    set_64_addr(USE_ADDR64_BCAST);
    set_16_addr(USE_ADDR16_UNKNOWN_OR_BCAST);

    // Set as apply
    set_transmit_request_options(15, options);

    set_transmit_data(16, remote_command, 3);
    
    build_api_frame_checksum(3 + REMOTE_AT_OVERHEAD_LENGTH);    

    transmit(3 + REMOTE_AT_OVERHEAD_LENGTH); 
}


void at_command_query(char msb, char lsb)
{
    char command[2] = {msb, lsb};
    
    build_api_frame_header(2 + REMOTE_AT_OVERHEAD_LENGTH);

    set_api_frame_type(ATCommand);
    set_api_frame_id(0x01);

    set_transmit_data(7, command, 2);

    build_api_frame_checksum(2 + REMOTE_AT_OVERHEAD_LENGTH);    

    transmit(2 + REMOTE_AT_OVERHEAD_LENGTH); 
}

void at_command_set(char msb, char lsb, char* parameter, int parameter_length)
{
    char command[2] = {msb, lsb};
    
    build_api_frame_header(parameter_length + AT_COMMAND_OVERHEAD_LENGTH);

    set_api_frame_type(ATCommand);
    set_api_frame_id(0x01);

    set_transmit_data(5, command, 2);
    set_transmit_data(7, parameter, parameter_length);

    build_api_frame_checksum(parameter_length + AT_COMMAND_OVERHEAD_LENGTH);    

    transmit(parameter_length + AT_COMMAND_OVERHEAD_LENGTH); 
}

void transmit(int packet_length)
{
    for (int i = 0; i < packet_length + 4; i++)
    {
        xbee.putc(TransmitBuffer[i]);
    }
    xbee_transmit_led = !xbee_transmit_led;
}

bool receive(frame_t* out_frame, int max_length)
{
    if (xbee.readable())
    {
        //Serial pc(USBTX, USBRX); // tx, rx
        static int curr_length = 0;
    
        frame_recv_state_t recv_state = wait_delimiter;
        frame_t* frame = out_frame;
        static char checksum = 0xFF;
    
        bool finished_frame = false;
    
        xbee_receive_led = !xbee_receive_led;
        while(curr_length < max_length && !finished_frame)
        {
            char current = xbee.getc();
            switch(recv_state)
            {
                case wait_delimiter:
                {
                    //pc.printf(":: delimiter x%x", current);
                    if (current == ZIGBEE_DELIMITER)
                    {
                        curr_length = 0;
                        recv_state = read_length_msb;
                        frame->length = 0;
                    }                
                    break;
                }
                case read_length_msb:  
                {
                    frame->length = (current << 8);
                    recv_state = read_length_lsb;
                    break;
                }
                case read_length_lsb:
                {                 
                    frame->length |= current;
                    //pc.printf("\n\rFrame length = %u", frame->length);  
                    checksum = 0xFF;
                    recv_state = read_frame_specific;
                    break;
                }
                case read_frame_specific:
                {
                    //pc.printf(":: read_frame_specific x%x", current);   
                    frame->buffer[curr_length++] = current;                
                    checksum -= current;
                    if (curr_length >= frame->length)
                    {
                        recv_state = read_checksum;
                    }
                    break;
                }
                case read_checksum:
                {
                   // pc.printf(":: read_checksum x%x", current);   
                    recv_state = wait_delimiter;
                    if (checksum == current)
                    {
                        finished_frame = true;
                    }
                    break;
                }
            }     
        }
        return finished_frame;    
    }
    return false;
}