This code is to collect data from the ADCs in burst mode, decimate the data, encapsulate it in a simple UDP-like packet and then transmit it over the serial port.

Dependencies:   mbed

comms.cpp

Committer:
jimurai
Date:
2010-08-27
Revision:
0:03e8a03052c9

File content as of revision 0:03e8a03052c9:

#include "mbed.h"
#include "comms.h"

void le2be_u16(uint8_t* buffer, uint16_t in_word) {  
        *buffer++ = (uint8_t)((in_word & 0xFF00) >> 8);
        *buffer = (uint8_t)(in_word & 0x00FF);
}

/**
 * This function is used to calculate a one's complement based checksum
 * as is commonly used in IP based protocols
 */
uint16_t chksum_u16(uint32_t in_word) {
    uint32_t temp = in_word & 0x0000FFFF;
    temp += (in_word & 0xFFFF0000)>>16;
    return (uint16_t)( (temp & 0x0000FFFF) + ((temp & 0xFFFF0000)>>16) );
}

/**
 * Transport constructor.
 * Set up the pseudo header and packet to be used in communications
 */
Transport::Transport (uint32_t src_addr, uint32_t dst_addr, uint32_t ID) {
    // Set up IPv4 pseudo header for checksum calculation
    pseudo_header_.src_addr = src_addr;
    pseudo_header_.dst_addr = dst_addr;
    pseudo_header_.protocol = PROTOCOL;
    pseudo_header_.length = sizeof(header_);
    // Set up default ports
    header_.src_port = PORT_BASE + ID;
    header_.dst_port = PORT_BASE;
    header_.length = sizeof(header_);
    // Calculate checksum of the pseudo-header: this should save some future recalculation
    uint32_t w_checksum = chksum_u16(src_addr);
    w_checksum = chksum_u16(dst_addr+w_checksum);
    w_checksum = chksum_u16(pseudo_header_.protocol+w_checksum);
    pseudo_header_.checksum = chksum_u16(pseudo_header_.length+w_checksum);
    // Now calculate checksum of the UDP packet header + pseudo-header
    w_checksum = chksum_u16(header_.src_port+pseudo_header_.checksum);
    w_checksum = chksum_u16(header_.dst_port+w_checksum);
    header_.checksum = chksum_u16(header_.length+w_checksum);
    // Load up the packet
    le2be_u16((packet_+0),header_.src_port);
    le2be_u16((packet_+2),header_.dst_port);
    le2be_u16((packet_+4),header_.length);
    le2be_u16((packet_+6),header_.checksum);
}

/**
 * Provides a pointer to a buffer containing a formatted packet and
 * the total length of said packet.
 */
void Transport::get_packet (uint8_t** buffer, uint16_t* length) {
    *buffer = packet_;
    *length = header_.length;
}

/**
 * Loads the transport packet with an array of 16bit samples.
 * This will require translating the words into big-endian.
 */
void Transport::load_data (uint16_t* buffer, uint16_t length) {
    uint8_t* pkt_ptr = packet_ + sizeof(header_);
    for (uint16_t i=0; i<length; i++) {
        le2be_u16(pkt_ptr,*buffer++);
        pkt_ptr += 2;
    }
    // Set the header length (in octets/bytes)
    header_.length = sizeof(header_) + (length<<1);
    le2be_u16((packet_+4),header_.length);
    // For now set the checksum to IGNORE
    header_.checksum = 0x0000;
    le2be_u16((packet_+6),header_.checksum);
}

/**
 * Set the destination port.
 */
void Transport::set_dst_port (uint16_t port) {
    // Store the port both in the local struct...
    header_.dst_port = port;
    // ...and in the transmission packet
    le2be_u16((packet_+2),port);
    //packet_[2] = (uint8_t)((port & 0xFF00) >> 8);
    //packet_[3] = (uint8_t)(port & 0x00FF);
}