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
Diff: WiconnectSerial.cpp
- Revision:
- 29:b6af04b77a56
- Child:
- 33:9b690d76eedf
- Child:
- 36:a30cbf4bdb13
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WiconnectSerial.cpp Mon Oct 27 13:42:26 2014 -0700 @@ -0,0 +1,202 @@ +/** + * 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; + } +}