Code APP3

Dependencies:   mbed EthernetInterface WebSocketClient mbed-rtos BufferedSerial

Fork of APP3_Lab by Jean-Philippe Fournier

xbee.cpp

Committer:
JayMcGee
Date:
2017-10-02
Revision:
29:56b6c15904e6
Parent:
27:3baf4701a047

File content as of revision 29:56b6c15904e6:


/***
*   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);

BufferedSerial xbee(p13, p14); // tx, rx
Serial pc_usb(USBTX, USBRX);
void Rx_interrupt();

#define BUFFER_SIZE 2048

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

volatile int rx_in = 0;
volatile int rx_out = 0;
/*
void Rx_interrupt()
{
    // Loop just in case more than one character is in UART's receive FIFO buffer
    // Stop if buffer full
    while ((xbee.readable()) && (((rx_in + 1) % BUFFER_SIZE) != rx_out)) {
        
        xbee_receive_led= !xbee_receive_led;
        ReceiveBuffer[rx_in] = xbee.getc();
        // Uncomment to Echo to USB serial to watch data flow
        pc_usb.putc(ReceiveBuffer[rx_in]);
        rx_in = (rx_in + 1) % BUFFER_SIZE;
    }
    return;
}
*/

bool addr_64_equal(zigbee_addr_64_t addr1, zigbee_addr_64_t addr2)
{
    if( addr1.addr_0 == addr2.addr_0 &&
        addr1.addr_1 == addr2.addr_1 &&
        addr1.addr_2 == addr2.addr_2 &&
        addr1.addr_3 == addr2.addr_3 &&
        addr1.addr_4 == addr2.addr_4 &&
        addr1.addr_5 == addr2.addr_5 &&
        addr1.addr_6 == addr2.addr_6 &&
        addr1.addr_7 == addr2.addr_7)
    {
        return true;
    }
    return false;
}

void xbee_init()
{
    // Setup a serial interrupt function to receive data
    xbee_receive_led = 0;
    //xbee.attach(&Rx_interrupt, Serial::RxIrq);    
    
    xbee_reset = 0;
    
    wait_ms(400);
    
    xbee_reset = 1;
    
    wait_ms(5000);    
}

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, zigbee_addr_64_t destination)
{
    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

    set_64_addr(destination);
    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, zigbee_addr_64_t destination)
{
    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

    set_64_addr(destination);
    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)
{
    static int curr_length = 0;

    static frame_recv_state_t recv_state = wait_delimiter;
    static char checksum = 0xFF;

    bool finished_frame = false;

    xbee_receive_led = !xbee_receive_led;
    while(xbee.readable() && curr_length < MAX_FRAME_SIZE && !finished_frame)
    {
        char current = xbee.getc();
        switch(recv_state)
        {
            case wait_delimiter:
            {
                if (current == ZIGBEE_DELIMITER)
                {
                    curr_length = 0;
                    recv_state = read_length_msb;
                    out_frame->length = 0;
                }                
                break;
            }
            case read_length_msb:  
            {
                out_frame->length = (current << 8);
                recv_state = read_length_lsb;
                break;
            }
            case read_length_lsb:
            {                 
                out_frame->length |= current;  
                checksum = 0xFF;
                recv_state = read_frame_specific;
                break;
            }
            case read_frame_specific:
            {   
                out_frame->buffer[curr_length++] = current;                
                checksum -= current;
                if (curr_length >= out_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;    
}