Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
TinyLink.cpp
- Committer:
- basilfx
- Date:
- 2014-10-02
- Revision:
- 1:32482de2ec7d
- Parent:
- 0:3fa89b8e47ad
File content as of revision 1:32482de2ec7d:
#include "TinyLink.h" #include "Crc.h" uint32_t TinyLink::checksumFrame(uint8_t* data, size_t length, uint8_t checksumHeader) { return crc::CRC32(crc::CRC32(data, length), checksumHeader); } uint8_t TinyLink::checksumHeader(uint16_t flags, uint16_t length) { uint8_t a = (flags & 0x00FF); uint8_t b = (flags & 0xFF00) >> 8; uint8_t c = (length & 0x00FF); uint8_t d = (length & 0xFF00) >> 8; return a ^ b ^ c ^ d; } TinyLink::TinyLink(FILE* _handle, uint8_t* _buffer, size_t _length) : handle(_handle), buffer(_buffer) { this->maxLength = _length - LEN_HEADER - LEN_BODY; this->state = WAITING_FOR_PREAMBLE; this->index = 0; } size_t TinyLink::write(frame_t* frame) { size_t result = 0; // Don't exceed max length if (frame->length > this->maxLength) { return 0; } // Send frame header uint32_t start = PREAMBLE; uint8_t checksumHeader = this->checksumHeader(frame->flags, frame->length); result += fwrite(&start, sizeof(uint32_t), 1, this->handle); result += fwrite(&frame->flags, sizeof(uint16_t), 1, this->handle); result += fwrite(&frame->length, sizeof(uint16_t), 1, this->handle); result += fwrite(&checksumHeader, sizeof(uint8_t), 1, this->handle); // Send body if (frame->length > 0 ) { uint32_t checksum2 = this->checksumFrame(frame->data, frame->length, checksumHeader); result += fwrite(frame->data, sizeof(uint8_t), frame->length, this->handle); result += fwrite(&checksum2, sizeof(uint32_t), 1, this->handle); } // Return number of bytes written return result; } size_t TinyLink::reset() { frame_t frame; frame.length = 0; frame.flags = FLAG_RESET; frame.data = NULL; return this->write(&frame); } size_t TinyLink::write(uint8_t* buffer, size_t length, uint16_t flags) { frame_t frame; frame.length = length; frame.flags = flags; frame.data = buffer; return this->write(&frame); } size_t TinyLink::write(uint8_t* buffer, size_t length) { frame_t frame; frame.length = length; frame.flags = FLAG_NONE; frame.data = buffer; return this->write(&frame); } int TinyLink::read(size_t limit, frame_t* frame) { return this->read(limit, frame, true); } int TinyLink::read(size_t limit, frame_t* frame, uint8_t ignoreDamaged) { // Read next up to `limit' bytes while (limit--) { fread(&this->buffer[this->index++], sizeof(uint8_t), 1, this->handle); // Decide what to do switch (this->state) { case WAITING_FOR_PREAMBLE: if (this->index >= LEN_PREAMBLE) { uint32_t start = *((uint32_t*) &this->buffer[this->index - 4]); if (start == PREAMBLE) { // Preamble found, advance state this->state = WAITING_FOR_HEADER; this->index = 0; } else if (this->index == this->maxLength + LEN_HEADER + LEN_BODY) { // Preamble not found and stream is full. Copy last four // bytes, because the next byte may form the preamble // together with the last three bytes. *((uint32_t*) this->buffer[0]) = start; this->index = 4; } } break; case WAITING_FOR_HEADER: if (this->index == LEN_HEADER) { uint16_t flags = (uint16_t) this->buffer[0]; uint16_t length = (uint16_t) this->buffer[2]; uint8_t checksum = this->buffer[4]; if (checksum == this->checksumHeader(flags, length) && length <= this->maxLength) { if (length > 0) { this->state = WAITING_FOR_BODY; } else { frame->flags = FLAG_RESET; frame->length = 0; frame->damaged = 0; frame->data = NULL; // Reset to start state this->state = WAITING_FOR_PREAMBLE; this->index = 0; // Return success return 1; } } else { // Reset to start state this->state = WAITING_FOR_PREAMBLE; this->index = 0; } } break; case WAITING_FOR_BODY: if (this->index == LEN_HEADER + frame->length + LEN_CRC) { uint16_t flags = (uint16_t) this->buffer[0]; uint16_t length = (uint16_t) this->buffer[2]; uint8_t checksumA = this->buffer[9]; uint32_t checksumB = (uint32_t) this->buffer[this->index - 4]; uint8_t damaged = (checksumB != this->checksumFrame(&this->buffer[LEN_HEADER], length, checksumA)); // Reset to start state this->state = WAITING_FOR_PREAMBLE; this->index = 0; // Copy bytes if (!damaged || !ignoreDamaged) { frame->flags = flags; frame->length = length; frame->damaged = damaged; memcpy(&this->buffer[LEN_HEADER], &frame->data, length); // Return success return 1; } } break; } } // No frames processed return 0; }