Subversion Repositories Code-Repo

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "maindefs.h"
#include "msg_queues.h"
#include "xbee.h"
#include "timers.h"
#include <usart.h>
#include <delays.h>

#pragma udata xbee_data
XBEE_FRAME data_frame;
#pragma udata
XBEE_DATA *xbee_data_ptr;
void *xbee_data_array_ptr;

/* Initialize variables used by this library */
void xbee_init(XBEE_DATA *xd) {
    TRISBbits.TRISB0 = 1;   // RB0 is CTS, set by XBee chip
    TRISBbits.TRISB1 = 0;   // RB1 is RTS, set by PIC
    TRISCbits.TRISC5 = 0;   // RC5 is Sleep
    
    LATBbits.LATB0 = 0; // Pin set high to signal stop sending data to XBee
    LATBbits.LATB1 = 0; // Pin set high to indicate stop sending data to PIC
    LATCbits.LATC5 = 0; // Pin set high to sleep XBee module

    xbee_data_ptr = xd;
    xbee_data_ptr->dataind = 0;
    xbee_data_ptr->checksum_sum = 0;
    xbee_data_ptr->read_state = XBEE_STATE_READ_START;

    xbee_data_ptr->rcv_frame.FRAME = &data_frame;

    // Grab a pointer to where the unique frame array starts
    xbee_data_array_ptr = xbee_data_ptr->rcv_frame.FRAME;
}

/* Here we handle the serial input from the UART interrupt */
void xbee_read_serial(unsigned char c) {
    // Reset on start bit and start saving data
    if (c == XBEE_START_DELIMITER) {
        // On detect start delimiter, clear out initial array
        xbee_data_ptr->dataind = 0;
        xbee_data_ptr->checksum_sum = 0;
        xbee_data_ptr->rcv_frame.start_delimiter = XBEE_START_DELIMITER;
        xbee_data_ptr->read_state = XBEE_STATE_READ_LENGTH_HIGH;
    } else {
        switch(xbee_data_ptr->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)
                xbee_data_ptr->rcv_frame.length.INT_16.char_value[1] = c;
                xbee_data_ptr->read_state = XBEE_STATE_READ_LENGTH_LOW;
                break;
            case XBEE_STATE_READ_LENGTH_LOW:
                // Read length (LSB)
                xbee_data_ptr->rcv_frame.length.INT_16.char_value[0] = c;
                xbee_data_ptr->read_state = XBEE_STATE_READ_FRAME_DATA;
                break;
            case XBEE_STATE_READ_FRAME_DATA:
                // Read unique frame data
                if (xbee_data_ptr->dataind < xbee_data_ptr->rcv_frame.length.INT_16.int_value) {
                    *((char*)xbee_data_array_ptr + xbee_data_ptr->dataind) = c;
                    xbee_data_ptr->checksum_sum += c;
                    xbee_data_ptr->dataind++;
                }
                // If total length is read, the next byte is the expected checksum
                if (xbee_data_ptr->dataind == xbee_data_ptr->rcv_frame.length.INT_16.int_value) {
                    xbee_data_ptr->read_state = XBEE_STATE_READ_CHECKSUM;
                }
                break;
            case XBEE_STATE_READ_CHECKSUM:
                // Calculate and compare checksum
                if (0xFF - xbee_data_ptr->checksum_sum == c) {
                    // Frame was recieved successfully
                    xbee_process_recieved_frame();
                    xbee_data_ptr->read_state = XBEE_STATE_READ_START;
                } else {
                // If checksum does not match, drop frame
                    DBG_PRINT_XBEE("XBEE: checksum mismatch\r\n");
                    xbee_data_ptr->read_state = XBEE_STATE_READ_START;
                }
                break;
        }
    }
}

/* This is called when a full frame arrives to process the frame data */
void xbee_process_recieved_frame() {
    char ret_status;
    
    // Here we want to process each frame and send the data to Main()
    // Send the frame to main() with the message type depending on the frame type
    switch(*((unsigned char *) xbee_data_array_ptr)) {
        case XBEE_RX_AT_COMMAND_RESPONSE:
            DBG_PRINT_XBEE("XBEE: parsing recieved AT command response frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_AT_COMMAND_RESPONSE, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_DATA_PACKET:
            DBG_PRINT_XBEE("XBEE: parsing recieved data recieved frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_DATA_PACKET, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_DATA_TX_STATUS:
            DBG_PRINT_XBEE("XBEE: parsing recieved TX status frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_DATA_TX_STATUS, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_IO_DATA_SAMPLE:
            DBG_PRINT_XBEE("XBEE: parsing recieved IO data sample frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_IO_DATA_SAMPLE, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_EXPLICIT_COMMAND:
            DBG_PRINT_XBEE("XBEE: parsing recieved explicit command frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_EXPLICIT_COMMAND, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_REMOTE_AT_COMMAND_RESPONSE:
            DBG_PRINT_XBEE("XBEE: parsing recieved remote AT command frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_REMOTE_AT_COMMAND_RESPONSE, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_ROUTE_RECORD:
            DBG_PRINT_XBEE("XBEE: parsing recieved route record frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_ROUTE_RECORD, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_NODE_IDENTIFICATION:
            DBG_PRINT_XBEE("XBEE: parsing recieved node identification frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_NODE_IDENTIFICATION, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        case XBEE_RX_FRAME_MODEM_STATUS:
            DBG_PRINT_XBEE("XBEE: parsing recieved modem status frame\r\n");
            ret_status = MQ_sendmsg_ToMainFromHigh(xbee_data_ptr->rcv_frame.length.INT_16.char_value[0], MSGTYPE_XBEE_RX_FRAME_MODEM_STATUS, (void *)xbee_data_array_ptr);
            if (ret_status < 0) {
                DBG_PRINT_XBEE("XBEE: (ERROR) send message to main failed with error %x\r\n", ret_status);
            }
            break;
        default:
            DBG_PRINT_XBEE("XBEE: (ERROR) unrecognized frame type\r\n");
    }
}

//void xbee_process_transmit_frame_interrupt(void) {
//    unsigned char i;
//    char length;
//
//    if (MQ_peek_FromMainToHigh() == MSGTYPE_XBEE_TX_FRAME) {
//        length = MQ_recvmsg_FromMainToHigh(MSGLEN, (unsigned char *) xbee_data_ptr->msgtype, (void *) xbee_data_array_ptr);
//        xbee_data_ptr->checksum_sum = 0;
//        Write2USART(XBEE_START_DELIMITER);
//        while (Busy2USART());
//        Write2USART(0x00);
//        while (Busy2USART());
//        Write2USART(length);
//        while (Busy2USART());
//        for (i = 0; i < length; i++) {
//            Write2USART(*((unsigned char *) xbee_data_array_ptr + i));
//            xbee_data_ptr->checksum_sum += *((unsigned char *) xbee_data_array_ptr + i);
//            while (Busy2USART());
//        }
//        Write2USART(0xFF - xbee_data_ptr->checksum_sum);
//        while (Busy2USART());
//    }
//}

void xbee_process_transmit_frame(void *data, unsigned char length) {
    unsigned char i;
    unsigned char checksum = 0;

    Write2USART(XBEE_START_DELIMITER);
    while (Busy2USART() || xbee_read_CTS());
    Write2USART(0x00);
    while (Busy2USART() || xbee_read_CTS());
    Write2USART(length);
    while (Busy2USART() || xbee_read_CTS());
    for (i = 0; i < length; i++) {
        Write2USART(*((unsigned char *) data + i));
        checksum += *((unsigned char *) data + i);
        while (Busy2USART() || xbee_read_CTS());
    }
    Write2USART(0xFF - checksum);
    while (Busy2USART());
}

void xbee_set_RTS(unsigned char c) {
    if (c) {
        LATBbits.LATB1 = 1; // Set high to stop receiving data
    } else {
        LATBbits.LATB1 = 0; // Set low to resume receiving data
    }
}

unsigned char xbee_read_CTS() {
    unsigned char c = PORTBbits.RB0;
    if (c) {
        return 0x1; // High indicates stop sending data
    } else {
        return 0x0; // Low indicates ok to send data
    }
}

void xbee_sleep() {
    LATCbits.LATC5 = 1;
}

void xbee_wake() {
    LATCbits.LATC5 = 0;
}