Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull changes from okra fork #10

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
8959169
Convert RSSI to dBm
Mar 30, 2022
826b81a
Implement retrieving RSSI for Espressif devices
Mar 30, 2022
c10c722
Merge branch 'wifi-rssi' into 'master'
amr-ayoub-okra Apr 5, 2022
8269d09
Add SSL support for Espressif devices
May 6, 2022
ce7a106
Merge branch 'espressif-ssl' into 'master'
LandryOkra May 9, 2022
e8c7abe
Handle WIFI DISCONNECT differently
May 10, 2022
ca1e0bb
Merge branch 'fix-wifi-disconnect' into 'master'
amr-ayoub-okra May 10, 2022
0257ae7
Fix delay when using modem auto detect
Jul 13, 2022
565be29
Merge branch 'delay_bug' into 'master'
amr-ayoub-okra Jul 14, 2022
3e931b7
Fix WiFi mode
Jul 19, 2022
3c095cb
Merge branch 'fix-wifi-mode' into 'master'
amr-ayoub-okra Jul 20, 2022
cef0514
Add delay to SIM800 driver
Sep 6, 2022
c4a0f64
SIM800: Use constant delay of 10ms between runs
Sep 7, 2022
18e15ce
Merge branch 'fix-sim800-delay' into 'master'
amr-ayoub-okra Sep 12, 2022
f797323
Add C as language to meson.build
Sep 16, 2022
0d9d9fe
Remove pointless buffer flush
Sep 22, 2022
4974898
Revert "Add delay to SIM800 driver"
Sep 22, 2022
1b97fab
Revert "SIM800: Use constant delay of 10ms between runs"
Sep 22, 2022
fcc0684
Bring back call to setLastRun() in ModemDetect
Sep 22, 2022
6b162ad
Merge branch 'fix-buffer-flush' into 'master'
amr-ayoub-okra Sep 26, 2022
b29b6fb
Remove pointless buffer flush also for Espressif
May 9, 2023
35e84b7
Add basic AT commands driver for CC1352P7 module
LandryOkra Jun 19, 2023
d309d72
Merge branch 'cp1352p7-support' into 'master'
amr-ayoub-okra Jun 19, 2023
48f56a5
Fix disconnect in SIM800 driver
Jun 29, 2023
c231e90
Add eventloop examples
Jun 29, 2023
1891403
Update README for new examples
Jun 29, 2023
d74cd67
Merge branch 'refactor-example' into 'master'
Jul 4, 2023
be10bcc
Merge branch 'wifi-flush-fix' into 'master'
amr-ayoub-okra Jul 12, 2023
b434eaf
Add `generic-linter` to repository
dmohns Oct 26, 2023
a46d595
Move docs to Github pages
dmohns Nov 7, 2023
90d33c6
Fix `Doxygen` installation
dmohns Nov 7, 2023
aa470c2
More fixes
dmohns Nov 7, 2023
0517678
Ignore Doxygen output from version control
dmohns Nov 7, 2023
5e9ee04
Merge branch 'okrasolar-master' into pull-changes-from-okra-fork
dmohns Feb 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ build
build_stm
build_linux
build_mbed
dep

# Ignore the Meson packagecache dir
packagecache
Expand Down
10 changes: 10 additions & 0 deletions cicada/commdevices/atcommdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,13 @@ Size ATCommDevice::serialRead(char* data, Size maxSize)

return 0;
}

void ATCommDevice::requestRSSI()
{
_rssi = INT16_MAX;
}

int16_t ATCommDevice::getRSSI()
{
return _rssi;
}
18 changes: 18 additions & 0 deletions cicada/commdevices/atcommdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ class ATCommDevice : public IPCommDevice
*/
virtual Size serialRead(char* data, Size maxSize);

/*!
* Request the RSSI (signal strength) from the modem. It can then be
* retreieved with getRSSI();
*/
void requestRSSI();

/*!
* Actually get the value for RSSI (signal strength), which has
* been requested by requestRSSI(). If the signal strength has been
* requested but not yet been retrieved, the returned value will
* be INT16_MAX.
*
* \return RSSI value in dBm, or INT16_MAX if a request is still pending.
*/
int16_t getRSSI();

protected:
void logStates(int8_t sendState, int8_t replyState);
bool handleDisconnect(int8_t nextState);
Expand All @@ -91,6 +107,8 @@ class ATCommDevice : public IPCommDevice
Size _bytesToReceive;
Size _bytesToRead;

int16_t _rssi;

static const char* _okStr;
static const char* _lineEndStr;
static const char* _quoteEndStr;
Expand Down
332 changes: 332 additions & 0 deletions cicada/commdevices/cc1352p7.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
/*
* Cicada communication library
* Copyright (C) 2023 Okrasolar
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/

#include "cicada/commdevices/cc1352p7.h"
#include "cicada/commdevices/atcommdevice.h"
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>

using namespace Cicada;

const uint16_t CC1352P7_MAX_RX = 1220; // Match network buffer of the modem

CC1352P7CommDevice::CC1352P7CommDevice(
IBufferedSerial& serial, uint8_t* readBuffer, uint8_t* writeBuffer, Size bufferSize) :
ATCommDevice(serial, readBuffer, writeBuffer, bufferSize)
{
resetStates();
}

CC1352P7CommDevice::CC1352P7CommDevice(IBufferedSerial& serial, uint8_t* readBuffer,
uint8_t* writeBuffer, Size readBufferSize, Size writeBufferSize) :
ATCommDevice(serial, readBuffer, writeBuffer, readBufferSize, writeBufferSize)
{
resetStates();
}

void CC1352P7CommDevice::resetStates()
{
_serial.flushReceiveBuffers();
_readBuffer.flush();
_writeBuffer.flush();
_lbFill = 0;
_sendState = 0;
_replyState = 0;
_connectState = IPCommDevice::notConnected;
_bytesToWrite = 0;
_bytesToReceive = 0;
_bytesToRead = 0;
_waitForReply = NULL;
_stateBooleans = LINE_READ;
}

bool CC1352P7CommDevice::fillLineBuffer()
{
// Buffer reply from modem in line buffer
// Returns true when enough data to be parsed is available.
if (_stateBooleans & LINE_READ) {
while (_serial.bytesAvailable()) {
char c = _serial.read();
_lineBuffer[_lbFill++] = c;
if (c == '\n' || c == '>' || _lbFill == LINE_MAX_LENGTH) {
_lineBuffer[_lbFill] = '\0';
_lbFill = 0;
return true;
}
}
}
return false;
}

bool CC1352P7CommDevice::sendCiprcvdata()
{
if (_serial.readBufferSize() - _serial.bytesAvailable() > 30
&& _readBuffer.spaceAvailable() > 0) {
// Make sure there is enough space in the serial buffer for the reply
Size bytesToReceive = _serial.readBufferSize() - _serial.bytesAvailable() - 30;
if (bytesToReceive > _bytesToReceive)
bytesToReceive = _bytesToReceive;
// Make sure there is enough space in the local device buffer
if (bytesToReceive > _readBuffer.spaceAvailable())
bytesToReceive = _readBuffer.spaceAvailable();
if (bytesToReceive > CC1352P7_MAX_RX)
bytesToReceive = CC1352P7_MAX_RX;

char sizeStr[6];
sprintf(sizeStr, "%u", (unsigned int)bytesToReceive);
_serial.write((const uint8_t*)"AT+CIPRECVDATA=");
_serial.write((const uint8_t*)sizeStr);
_serial.write((const uint8_t*)_lineEndStr);
return true;
} else {
return false;
}
}

bool CC1352P7CommDevice::parseCiprecvdata()
{
if (strncmp(_lineBuffer, "+CIPRECVDATA", 12) == 0) {
int bytesToRead;
sscanf(_lineBuffer + 13, "%d", &bytesToRead);
_bytesToReceive -= bytesToRead;
_bytesToRead += bytesToRead;
_stateBooleans &= ~LINE_READ;
return true;
}

return false;
}

void CC1352P7CommDevice::run()
{
// If the serial device is net yet open, try to open it
if (!_serial.isOpen()) {
if (!_serial.open()) {
_sendState = serialError;
}
return;
}

// If a modem reset is pending, handle it
if (_stateBooleans & RESET_PENDING) {
_serial.flushReceiveBuffers();
_bytesToRead = 0;
_bytesToReceive = 0;
_bytesToWrite = 0;
_sendState = sendCipclose;
_replyState = okReply;
_waitForReply = NULL;
_stateBooleans &= ~RESET_PENDING;
if (_connectState >= intermediate) {
connect();
}
}

// Buffer data from the modem
bool parseLine = fillLineBuffer();

// Check if there is data from the modem
if (parseLine) {

// Log the current modem states
logStates(_sendState, _replyState);

// Handle error states
if (strncmp(_lineBuffer, "ERROR", 5) == 0
|| (_sendState >= connected && strncmp(_lineBuffer, "SEND FAIL", 9) == 0)) {
_stateBooleans |= RESET_PENDING;
_connectState = generalError;
_waitForReply = NULL;
return;
}

// If sent a command, process standard reply
if (_waitForReply) {
if (strncmp(_lineBuffer, _waitForReply, strlen(_waitForReply)) == 0) {
_waitForReply = NULL;
}
}

// Process incoming data which need special treatment
switch (_replyState) {
case parseStateCiprecvdata:
if (parseCiprecvdata()) {
_replyState = okReply;
_sendState = receiving;
}
break;

default:
break;
}

// In connected state, check for new data or IP connection close
if (_sendState >= connected) {
if (strncmp(_lineBuffer, "+IPD,", 4) == 0) {
int bytes;
sscanf(_lineBuffer + 5, "%d", &bytes);
_bytesToReceive = bytes;
_stateBooleans |= DATA_PENDING;
} else if (strncmp(_lineBuffer, "CLOSED", 6) == 0) {
_stateBooleans &= ~IP_CONNECTED;
}
}
}

// When disconnecting was requested, flush read buffer first
else if ((_stateBooleans & DISCONNECT_PENDING) && _sendState == receiving) {
flushReadBuffer();
}

// Don't go on when waiting for a reply
if (_waitForReply || _replyState != okReply)
return;

// Don't go on if space in write buffer is low
if (_serial.spaceAvailable() < 20)
return;

// Connection state machine
switch (_sendState) {
case notConnected:
_connectState = IPCommDevice::notConnected;
handleConnect(connecting);
break;

case connecting:
_connectState = IPCommDevice::intermediate;
_stateBooleans |= LINE_READ;
_waitForReply = _okStr;
_sendState = sendCipstart;
sendCommand("ATE0");
break;

case sendCipstart: {
char portStr[6];
snprintf(portStr, sizeof(portStr), "%u", _port);

_serial.write((const uint8_t*)"AT+CIPSTART");
if (_type == UDP) {
_serial.write((const uint8_t*)"=\"UDP\",\"");
} else {
_serial.write((const uint8_t*)"=\"TCP\",\"");
}
// TODO: Escape characters
_serial.write((const uint8_t*)_host);
_serial.write((const uint8_t*)"\",");
_serial.write((const uint8_t*)portStr);
_serial.write((const uint8_t*)_lineEndStr);

_waitForReply = _okStr;
_sendState = finalizeConnect;
break;
}

case finalizeConnect:
_connectState = IPCommDevice::connected;
_sendState = connected;
_stateBooleans |= IP_CONNECTED;
break;

case connected:
if (_writeBuffer.bytesAvailable()) {
if (prepareSending(false)) {
_serial.write((const uint8_t*)_lineEndStr);
_connectState = IPCommDevice::transmitting;
_sendState = sendDataState;
}
} else if (_stateBooleans & DATA_PENDING) {
_stateBooleans &= ~DATA_PENDING;
_connectState = IPCommDevice::receiving;
_sendState = sendCiprecvdata;
} else {
_connectState = IPCommDevice::connected;
if (_stateBooleans & IP_CONNECTED) {
if (handleDisconnect(sendCipclose)) {
}
} else {
_stateBooleans &= ~DISCONNECT_PENDING;
_sendState = finalizeDisconnect;
}
}
break;

// States after connecting

case sendDataState:
sendData();
_waitForReply = _okStr;
_sendState = connected;
break;

case sendCiprecvdata:
if (handleDisconnect(sendCipclose)) {
break;
}

if (_bytesToReceive > 0) {
if (sendCiprcvdata()) {
_sendState = waitReceive;
_replyState = parseStateCiprecvdata;
}
} else {
_sendState = connected;
}

break;

case waitReceive:
break;

case receiving:
if (_bytesToRead > 0) {
if (receive()) {
_replyState = okReply;
_waitForReply = _okStr;
}
} else if (_bytesToReceive > 0) {
_sendState = sendCiprecvdata;
} else {
_sendState = connected;
}
break;

case sendCipclose:
_connectState = IPCommDevice::intermediate;
_waitForReply = _okStr;
_sendState = finalizeDisconnect;
sendCommand("AT+CIPCLOSE");
break;

case finalizeDisconnect:
_stateBooleans &= ~IP_CONNECTED;
_connectState = IPCommDevice::notConnected;
_sendState = notConnected;
break;

default:
break;
}
}
Loading
Loading