Subversion Repositories Code-Repo

Rev

Rev 155 | Blame | Last modification | View Log | RSS feed

#include <xc.h>
#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "xbee.h"
#include "uart.h"

static XBEE_DATA *xbee_data_p;
static void *xbee_data_frame;
static void *xbee_frame;

/* Initialize variables used by this library */
void XBee_Init(XBEE_DATA *data) {
    xbee_data_p = data;
    XBEE_CTS_TRIS = 1; // RB0 is CTS, set by XBee chip
    XBEE_RTS_TRIS = 0; // RB1 is RTS, set by PIC

    XBEE_CTS_LAT = 0; // Pin set high to signal stop sending data to XBee
    XBEE_RTS_LAT = 0; // Pin set high to indicate stop sending data to PIC

    xbee_data_p->dataind = 0;
    xbee_data_p->checksum_sum = 0;
    xbee_data_p->frame_rdy = 0;
    xbee_data_p->escape_flag = 0;
    xbee_data_p->read_state = XBEE_STATE_READ_START;

//    memset(&xbee_data, 0, 32);
    
    // Grab a pointer to where the unique frame array starts
    xbee_data_frame = &(xbee_data_p->rcv_frame.FRAME);
    xbee_frame = &(xbee_data_p->rcv_frame);
}

/* Here we handle the serial input from the UART interrupt */
void XBee_Serial_In(char c) {
    // For some reason writing the length straight to xbee_data doesnt seem to work
    //  so we work around it by pointing to the length bytes directly
    XBEE_ADDRESS_16 *length = xbee_frame + 1;
    
#ifdef XBEE_USE_ESCAPE_CHAR
    if (c == XBEE_ESCAPE_CHAR) {
        // Next byte needs is an escaped char
        xbee_data_p->escape_flag = 1;
        return;
    }

    if (xbee_data_p->escape_flag) {
        // XOR byte with 0x20 to get escaped char
        c ^= XBEE_ESCAPE_VAL;
        xbee_data_p->escape_flag = 0;
    }
#endif
    // Reset on start bit and start saving data
    if (c == XBEE_START_DELIMITER) {
        // On detect start delimiter, clear out initial array
        xbee_data_p->dataind = 0;
        xbee_data_p->checksum_sum = 0;
        xbee_data_p->frame_rdy = 0;
        xbee_data_p->read_state = XBEE_STATE_READ_LENGTH_HIGH;
        *((char *)xbee_frame) = XBEE_START_DELIMITER;
    } else {
        switch (xbee_data_p->read_state) {
            case XBEE_STATE_READ_START:
                // Do nothing and wait till start bit is read
                break;
            case XBEE_STATE_READ_LENGTH_HIGH:
                // Read length (MSB)
                length->INT_16.char_value[1] = c;
                xbee_data_p->read_state = XBEE_STATE_READ_LENGTH_LOW;
                break;
            case XBEE_STATE_READ_LENGTH_LOW:
                // Read length (LSB)
                length->INT_16.char_value[0] = c;
                xbee_data_p->read_state = XBEE_STATE_READ_FRAME_DATA;
                break;
            case XBEE_STATE_READ_FRAME_DATA:
                // Read unique frame data
                if (xbee_data_p->dataind < xbee_data_p->rcv_frame.length.INT_16.int_value) {
                    *((char*) xbee_data_frame + xbee_data_p->dataind) = c;
                    xbee_data_p->checksum_sum += c;
                    xbee_data_p->dataind++;
                }
                // If total length is read, the next byte is the expected checksum
                if (xbee_data_p->dataind == xbee_data_p->rcv_frame.length.INT_16.int_value) {
                    xbee_data_p->read_state = XBEE_STATE_READ_CHECKSUM;
                }
                break;
            case XBEE_STATE_READ_CHECKSUM:
                // Calculate and compare checksum
                if (0xFF - xbee_data_p->checksum_sum == c) {
                    // Frame was recieved successfully
                    xbee_data_p->frame_rdy = 1;
//                    XBee_Process_Received_Frame();
                } else {
                    // If checksum does not match, drop frame
                    char output[32];
                    sprintf(output, "XBEE: checksum mismatch\r\n");
                    DBG_PRINT_XBEE(output, strlen(output));
                }
                xbee_data_p->read_state = XBEE_STATE_READ_START;
                break;
        }
    }
}

/* This processes the frame data within the interrupt. Dont use this. */
void XBee_Process_Received_Frame() {
//    DBG_PRINT_XBEE("Length: %d\r\n", xbee_data_p->rcv_frame.length.INT_16.int_value);
    // Here we process the received frame depending on the frame type
    char output[64];
    switch (*((char *) xbee_data_frame)) {
        case XBEE_RX_AT_COMMAND_RESPONSE:
            sprintf(output, "XBEE: parsing recieved AT command response frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_DATA_PACKET:
            sprintf(output, "XBEE: parsing recieved data frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_DATA_TX_STATUS:
            sprintf(output, "XBEE: parsing recieved TX status frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_IO_DATA_SAMPLE:
            sprintf(output, "XBEE: parsing recieved IO data sample frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_EXPLICIT_COMMAND:
            sprintf(output, "XBEE: parsing recieved explicit command frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_REMOTE_AT_COMMAND_RESPONSE:
            sprintf(output, "XBEE: parsing recieved remote AT command frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_ROUTE_RECORD:
            sprintf(output, "XBEE: parsing recieved route record frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_NODE_IDENTIFICATION:
            sprintf(output, "XBEE: parsing recieved node identification frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        case XBEE_RX_FRAME_MODEM_STATUS:
            sprintf(output, "XBEE: parsing recieved modem status frame\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
            break;
        default:
            sprintf(output, "XBEE: (ERROR) unrecognized frame type\r\n");
            DBG_PRINT_XBEE(output, strlen(output));
    }
}

unsigned int XBee_Get_Received_Frame(char *frame) {
    if (!xbee_data_p->frame_rdy) {
        return 0;
    } else {
        memcpy(frame, xbee_data_frame, xbee_data_p->rcv_frame.length.INT_16.int_value);
        xbee_data_p->frame_rdy = 0; // Reset frame ready status
        return xbee_data_p->rcv_frame.length.INT_16.int_value;
    }
}

void XBee_Process_Transmit_Frame(char *data, char length) {
#ifdef XBEE_USE_ESCAPE_CHAR
    unsigned int i = 0;
    char chksum = 0;

    // Write the start bit and length
    UART1_WriteC(XBEE_START_DELIMITER);
    UART1_WriteC(0);
    UART1_WriteC(length);

    // Write the frame data
    for (i = 0; i < length; i++) {
        chksum += data[i];
        if (data[i] == XBEE_START_DELIMITER ||     \
                data[i] == XBEE_ESCAPE_CHAR ||     \
                data[i] == XBEE_XON ||     \
                data[i] == XBEE_XOFF) {
            UART1_WriteC(XBEE_ESCAPE_CHAR);
            UART1_WriteC(data[i] ^ XBEE_ESCAPE_VAL);
        } else {
            UART1_WriteC(data[i]);
        }
    }
    // Write the checksum
    if (chksum == XBEE_START_DELIMITER ||     \
                chksum == XBEE_ESCAPE_CHAR ||     \
                chksum == XBEE_XON ||     \
                chksum == XBEE_XOFF) {
        UART1_WriteC(XBEE_ESCAPE_CHAR);
        UART1_WriteC(chksum ^ XBEE_ESCAPE_VAL);
    } else {
        UART1_WriteC(0xFF - chksum);
    }
#else
    unsigned int i = 0;
    char chksum = 0;

    UART1_WriteC(XBEE_START_DELIMITER);
    UART1_WriteC(0);
    UART1_WriteC(length);
    for (i = 0; i < length; i++) {
        chksum += data[i];
        UART1_WriteC(data[i]);
    }
    UART1_WriteC(0xFF - chksum);
#endif
}

void XBee_Set_RTS(char c) {
    if (c) {
        XBEE_RTS_LAT = 1; // Set high to stop receiving data
    } else {
        XBEE_RTS_LAT = 0; // Set low to resume receiving data
    }
}

char XBee_Read_CTS() {
    char c = XBEE_CTS_PORT;
    if (c) {
        return 0x1; // High indicates stop sending data
    } else {
        return 0x0; // Low indicates ok to send data
    }
}

void XBee_Convert_Endian_64(XBEE_ADDRESS_64 *src) {
    char tmp[2];
    tmp[0] = src->UPPER_32.char_value[3];
    tmp[1] = src->UPPER_32.char_value[2];
    src->UPPER_32.char_value[3] = src->UPPER_32.char_value[0];
    src->UPPER_32.char_value[2] = src->UPPER_32.char_value[1];
    src->UPPER_32.char_value[1] = tmp[1];
    src->UPPER_32.char_value[0] = tmp[0];

    tmp[0] = src->LOWER_32.char_value[3];
    tmp[1] = src->LOWER_32.char_value[2];
    src->LOWER_32.char_value[3] = src->LOWER_32.char_value[0];
    src->LOWER_32.char_value[2] = src->LOWER_32.char_value[1];
    src->LOWER_32.char_value[1] = tmp[1];
    src->LOWER_32.char_value[0] = tmp[0];
}

void XBee_Convert_Endian_16(XBEE_ADDRESS_16 *src) {
    char tmp;
    tmp = src->INT_16.char_value[0];
    src->INT_16.char_value[0] = src->INT_16.char_value[1];
    src->INT_16.char_value[1] = tmp;
}