Host library for controlling a WiConnect enabled Wi-Fi module.
Dependents: wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more
WiconnectSerial.cpp
- Committer:
- dan_ackme
- Date:
- 2014-10-27
- Revision:
- 29:b6af04b77a56
- Child:
- 33:9b690d76eedf
- Child:
- 36:a30cbf4bdb13
File content as of revision 29:b6af04b77a56:
/** * ACKme WiConnect Host Library is licensed under the BSD licence: * * Copyright (c)2014 ACKme Networks. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include "Wiconnect.h" #include "internal/common.h" #ifndef WICONNECT_SERIAL_RX_BUFFER #error WICONNECT_SERIAL_RX_BUFFER NOT defined NOT currently supported #endif typedef struct { uint16_t size; volatile uint16_t count; uint8_t *start, *end; volatile uint8_t *head; volatile uint8_t *tail; } SerialRxBuffer; /*************************************************************************************************/ WiconnectSerial::WiconnectSerial(const SerialConfig &config, Wiconnect *wiconnect) : RawSerial(config.tx, config.rx) { ct_assert(sizeof(ringBuffer) >= sizeof(SerialRxBuffer)); baud(config.baud); SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer; memset(rxBuffer, 0, sizeof(SerialRxBuffer)); bufferAlloc = false; if(config.serialRxBufferSize > 0) { if(config.serialRxBuffer != NULL) { rxBuffer->start = (uint8_t*)config.serialRxBuffer; } #ifdef WICONNECT_ENABLE_MALLOC else { wiconnect_assert(wiconnect, "WiconnectSerial(), malloc not defined", wiconnect->_malloc != NULL); rxBuffer->start = (uint8_t*)wiconnect->_malloc(config.serialRxBufferSize); wiconnect_assert(wiconnect, "WiconnectSerial(), malloc failed", rxBuffer->start != NULL); bufferAlloc = true; } #endif rxBuffer->head = rxBuffer->tail = (volatile uint8_t*)rxBuffer->start; rxBuffer->end = (uint8_t*)rxBuffer->head + config.serialRxBufferSize; rxBuffer->size = config.serialRxBufferSize; attach(this, &WiconnectSerial::rxIrqHandler, SerialBase::RxIrq); } } /*************************************************************************************************/ WiconnectSerial::~WiconnectSerial() { #ifdef WICONNECT_ENABLE_MALLOC if(bufferAlloc) { SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer; Wiconnect::getInstance()->_free(rxBuffer->start); } #endif } /*************************************************************************************************/ void WiconnectSerial::initialize(void) { } /*************************************************************************************************/ void WiconnectSerial::flush(void) { while (readable()) { int c = getc(); } SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer; rxBuffer->tail = rxBuffer->head = rxBuffer->start; rxBuffer->count = 0; } /*************************************************************************************************/ int WiconnectSerial::write(const void *data, int bytesToWrite, TimerTimeout timeoutMs) { uint8_t *ptr = (uint8_t*)data; int remaining = bytesToWrite; while(remaining > 0) { if(!writeable()) { timeoutTimer.reset(); while(!writeable()) { if(timeoutMs == 0) { if(timeoutTimer.readMs() > 0) { goto exit; } } else { if(timeoutTimer.readMs() >= timeoutMs) { goto exit; } } } } putc(*ptr); ++ptr; --remaining; } exit: return bytesToWrite - remaining; } /*************************************************************************************************/ int WiconnectSerial::read(void *data, int bytesToRead, TimerTimeout timeoutMs) { SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer; uint8_t *ptr = (uint8_t*)data; int remaining = bytesToRead; while(remaining > 0) { if(rxBuffer->count == 0) { if(timeoutMs == 0) { break; } else { timeoutTimer.reset(); while(rxBuffer->count == 0) { if(timeoutTimer.readMs() >= timeoutMs) { goto exit; } } } } *ptr++ = *rxBuffer->tail++; --remaining; --rxBuffer->count; if(rxBuffer->tail >= rxBuffer->end) rxBuffer->tail = rxBuffer->start; } exit: return bytesToRead - remaining; } /*************************************************************************************************/ void WiconnectSerial::rxIrqHandler(void) { SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer; while (readable() && rxBuffer->count < rxBuffer->size) { *rxBuffer->head++ = (uint8_t)getc(); ++rxBuffer->count; if(rxBuffer->head >= rxBuffer->end) rxBuffer->head = rxBuffer->start; } }