From 4a2858384639f1ec9d91f303b4b2286c130bd0d3 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Fri, 7 Aug 2020 18:00:30 +0200 Subject: [PATCH] Initial work on SPI support. --- .gitmodules | 2 +- Sming/Components/Hosted-Lib/src/SpiHosted.cpp | 71 +++++++ .../Components/Hosted/app/app/application.cpp | 29 +-- Sming/Components/Hosted/app/component.mk | 3 + .../Hosted/app/src/DigitalHosted.cpp | 27 +++ .../Components/Hosted/app/src/DigitalHosted.h | 12 ++ Sming/Components/Hosted/app/src/SpiHosted.cpp | 46 ++++ Sming/Components/Hosted/app/src/SpiHosted.h | 12 ++ Sming/Components/Hosted/proto/hosted.pb.c | 29 +++ Sming/Components/Hosted/proto/hosted.pb.h | 198 +++++++++++++++++- Sming/Components/Hosted/proto/hosted.proto | 62 ++++++ Sming/Components/Hosted/src/HostedCommon.h | 5 +- Sming/Components/Hosted/src/HostedServer.h | 5 + Sming/Components/Hosted/src/HostedUtils.cpp | 42 ++++ Sming/Components/Hosted/src/HostedUtils.h | 14 ++ 15 files changed, 535 insertions(+), 22 deletions(-) create mode 100644 Sming/Components/Hosted-Lib/src/SpiHosted.cpp create mode 100644 Sming/Components/Hosted/app/src/DigitalHosted.cpp create mode 100644 Sming/Components/Hosted/app/src/DigitalHosted.h create mode 100644 Sming/Components/Hosted/app/src/SpiHosted.cpp create mode 100644 Sming/Components/Hosted/app/src/SpiHosted.h create mode 100644 Sming/Components/Hosted/src/HostedUtils.cpp create mode 100644 Sming/Components/Hosted/src/HostedUtils.h diff --git a/.gitmodules b/.gitmodules index e0c78b6f44..82fabbef3b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,7 +29,7 @@ [submodule "nanopb"] path = Sming/Components/nanopb/nanopb url = https://github.com/nanopb/nanopb.git - + ignore = dirty [submodule "esptool"] path = Sming/Arch/Esp8266/Components/esptool/esptool url = https://github.com/espressif/esptool diff --git a/Sming/Components/Hosted-Lib/src/SpiHosted.cpp b/Sming/Components/Hosted-Lib/src/SpiHosted.cpp new file mode 100644 index 0000000000..8d95e0f50b --- /dev/null +++ b/Sming/Components/Hosted-Lib/src/SpiHosted.cpp @@ -0,0 +1,71 @@ +#include +#include +#include + +extern HostedClient* hostedClient; + +// define the static singleton +SPIClass SPI; + +void SPIClass::begin() +{ + NEW_HD_COMMAND(message, SpiBeginTransaction, { + command->has_settings = 0; + }); + + hostedClient->send(&message); +} + +void SPIClass::beginTransaction(SPISettings mySettings) +{ + NEW_HD_COMMAND(message, SpiBeginTransaction, { + command->has_settings = 1; + command->settings.speed = mySettings.speed; + command->settings.byteOrder = (SpiSettings_ByteOrder)mySettings.byteOrder; + command->settings.dataMode = (SpiSettings_DataMode)mySettings.dataMode; + }); + + hostedClient->send(&message); +} + +/** @brief transfer(uint8_t *buffer, size_t numberBytes) + * @param buffer in/out + * @param numberBytes length of buffer + * + * SPI transfer is based on a simultaneous send and receive: + * The buffered transfers does split up the conversation internaly into 64 byte blocks. + * The received data is stored in the buffer passed by reference. + * (the data past in is replaced with the data received). + * + * SPI.transfer(buffer, size) : memory buffer of length size + */ +void SPIClass::transfer(uint8_t* buffer, size_t numberBytes) +{ + PbData data; + data.value = buffer; + data.length = numberBytes; + + NEW_HD_COMMAND(message, SpiTransfer, { + command->data.arg = (void*)&data; + command->data.funcs.encode = &pbEncodeData; + }); + + hostedClient->send(&message); + HostedCommand response = hostedClient->wait(); + + MemoryDataStream* resultData = (MemoryDataStream*)response.payload.responseSpiTransfer.data.arg; + if(resultData == nullptr) { + memset(buffer, 0, numberBytes); + return; + } + + resultData->readBytes((char *)buffer, numberBytes); + delete resultData; +} + + +uint32_t SPIClass::transfer32(uint32_t val, uint8_t bits) +{ + // TODO: + return 0; +} diff --git a/Sming/Components/Hosted/app/app/application.cpp b/Sming/Components/Hosted/app/app/application.cpp index d762315760..a52ac532ce 100644 --- a/Sming/Components/Hosted/app/app/application.cpp +++ b/Sming/Components/Hosted/app/app/application.cpp @@ -1,6 +1,5 @@ #include #include -#include // If you want, you can define WiFi settings globally in Eclipse Environment Variables #ifndef WIFI_SSID @@ -11,6 +10,15 @@ HostedServer hostedServer; TcpServer* tcpServer; +namespace Hosted { + namespace Digital { + void registerCommands(HostedServer& server); + } + namespace Spi { + void registerCommands(HostedServer& server); + } +} + // Will be called when WiFi station was connected to AP void connectOk(IpAddress ip, IpAddress mask, IpAddress gateway) { @@ -39,24 +47,9 @@ void connectOk(IpAddress ip, IpAddress mask, IpAddress gateway) void init() { - // Register Command Handlers - hostedServer.registerCommand(HostedCommand_requestPinMode_tag, [](HostedCommand *request, HostedCommand *response)-> int { - pinMode((uint16_t)request->payload.requestPinMode.pin, (uint8_t)request->payload.requestPinMode.mode); - return 0; - }); + Hosted::Digital::registerCommands(hostedServer); + Hosted::Spi::registerCommands(hostedServer); - hostedServer.registerCommand(HostedCommand_requestDigitalWrite_tag, [](HostedCommand *request, HostedCommand *response)-> int { - digitalWrite((uint16_t)request->payload.requestDigitalWrite.pin, (uint8_t)request->payload.requestDigitalWrite.value); - return 0; - }); - - hostedServer.registerCommand(HostedCommand_requestDigitalRead_tag, [](HostedCommand *request, HostedCommand *response)-> int { - uint8_t result = digitalRead((uint16_t)request->payload.requestDigitalRead.pin); - response->which_payload = HostedCommand_responseDigitalRead_tag; - response->payload.responseDigitalRead.value = result; - - return 0; - }); // Connect to same AP as the client application WifiStation.enable(true); diff --git a/Sming/Components/Hosted/app/component.mk b/Sming/Components/Hosted/app/component.mk index 9f991745a3..b4ead4dbba 100644 --- a/Sming/Components/Hosted/app/component.mk +++ b/Sming/Components/Hosted/app/component.mk @@ -5,3 +5,6 @@ ENABLE_HOSTED := ## SPIFFS options DISABLE_SPIFFS := 1 # SPIFF_FILES = files + +COMPONENT_APPCODE := src +COMPONENT_INCDIRS := $(COMPONENT_SRCDIRS) diff --git a/Sming/Components/Hosted/app/src/DigitalHosted.cpp b/Sming/Components/Hosted/app/src/DigitalHosted.cpp new file mode 100644 index 0000000000..4a62fcb650 --- /dev/null +++ b/Sming/Components/Hosted/app/src/DigitalHosted.cpp @@ -0,0 +1,27 @@ +#include "DigitalHosted.h" + +namespace Hosted { +namespace Digital { + + void registerCommands(HostedServer& server) + { + // Register Command Handlers + server.registerCommand(HostedCommand_requestPinMode_tag, [](HostedCommand *request, HostedCommand *response)-> int { + pinMode((uint16_t)request->payload.requestPinMode.pin, (uint8_t)request->payload.requestPinMode.mode); + return 0; + }); + + server.registerCommand(HostedCommand_requestDigitalWrite_tag, [](HostedCommand *request, HostedCommand *response)-> int { + digitalWrite((uint16_t)request->payload.requestDigitalWrite.pin, (uint8_t)request->payload.requestDigitalWrite.value); + return 0; + }); + + server.registerCommand(HostedCommand_requestDigitalRead_tag, [](HostedCommand *request, HostedCommand *response)-> int { + uint8_t result = digitalRead((uint16_t)request->payload.requestDigitalRead.pin); + response->which_payload = HostedCommand_responseDigitalRead_tag; + response->payload.responseDigitalRead.value = result; + + return 0; + }); + } +}} diff --git a/Sming/Components/Hosted/app/src/DigitalHosted.h b/Sming/Components/Hosted/app/src/DigitalHosted.h new file mode 100644 index 0000000000..9913134f98 --- /dev/null +++ b/Sming/Components/Hosted/app/src/DigitalHosted.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include + +namespace Hosted { + namespace Digital { + + void registerCommands(HostedServer& server); + } +} diff --git a/Sming/Components/Hosted/app/src/SpiHosted.cpp b/Sming/Components/Hosted/app/src/SpiHosted.cpp new file mode 100644 index 0000000000..3a80658d45 --- /dev/null +++ b/Sming/Components/Hosted/app/src/SpiHosted.cpp @@ -0,0 +1,46 @@ +#include "SpiHosted.h" +#include + +namespace Hosted { +namespace Spi { + + void registerCommands(HostedServer& server) + { + // Register Command Handlers + server.registerCommand(HostedCommand_requestSpiBeginTransaction_tag, [](HostedCommand *request, HostedCommand *response)-> int { + if(request->payload.requestSpiBeginTransaction.has_settings) { + SPI.begin(); + } + else { + SPISettings settings(request->payload.requestSpiBeginTransaction.settings.speed, + request->payload.requestSpiBeginTransaction.settings.byteOrder, + request->payload.requestSpiBeginTransaction.settings.dataMode); + SPI.beginTransaction(settings); + } + + return 0; + }); + + server.registerCommand(HostedCommand_requestSpiTransfer_tag, [](HostedCommand *request, HostedCommand *response)-> int { + PbData* responseData = new PbData; + responseData->length = 0; + + MemoryDataStream* data = (MemoryDataStream*)request->payload.requestSpiTransfer.data.arg; + if(data != nullptr) { + size_t available = data->available(); + uint8_t* buffer = new uint8_t[available]; + size_t length = data->readBytes((char *)&buffer, available); + SPI.transfer(buffer, length); + responseData->value = buffer; + responseData->length = length; + + delete data; + } + + response->payload.responseSpiTransfer.data.funcs.encode = &pbEncodeData; + response->payload.responseSpiTransfer.data.arg = (void* )responseData; + + return 0; + }); + } +}} diff --git a/Sming/Components/Hosted/app/src/SpiHosted.h b/Sming/Components/Hosted/app/src/SpiHosted.h new file mode 100644 index 0000000000..94f9111949 --- /dev/null +++ b/Sming/Components/Hosted/app/src/SpiHosted.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include + +namespace Hosted { + namespace Spi { + + void registerCommands(HostedServer& server); + } +} diff --git a/Sming/Components/Hosted/proto/hosted.pb.c b/Sming/Components/Hosted/proto/hosted.pb.c index 7bb50c07db..f85e9d98d5 100644 --- a/Sming/Components/Hosted/proto/hosted.pb.c +++ b/Sming/Components/Hosted/proto/hosted.pb.c @@ -18,9 +18,38 @@ PB_BIND(RequestDigitalRead, RequestDigitalRead, AUTO) PB_BIND(ResponseDigitalRead, ResponseDigitalRead, AUTO) +PB_BIND(SpiSettings, SpiSettings, AUTO) + + +PB_BIND(RequestSpiBeginTransaction, RequestSpiBeginTransaction, AUTO) + + +PB_BIND(RequestSpiEndTransaction, RequestSpiEndTransaction, AUTO) + + +PB_BIND(RequestSpiTransfer, RequestSpiTransfer, AUTO) + + +PB_BIND(ResponseSpiTransfer, ResponseSpiTransfer, AUTO) + + +PB_BIND(RequestSpiWrite, RequestSpiWrite, AUTO) + + +PB_BIND(ResponseSpiWrite, ResponseSpiWrite, AUTO) + + +PB_BIND(RequestSpiRead, RequestSpiRead, AUTO) + + +PB_BIND(ResponseSpiRead, ResponseSpiRead, AUTO) + + PB_BIND(HostedCommand, HostedCommand, AUTO) + + diff --git a/Sming/Components/Hosted/proto/hosted.pb.h b/Sming/Components/Hosted/proto/hosted.pb.h index 81837b79bf..47da2da93e 100644 --- a/Sming/Components/Hosted/proto/hosted.pb.h +++ b/Sming/Components/Hosted/proto/hosted.pb.h @@ -20,11 +20,43 @@ typedef enum _PinMode { PinMode_INPUT_PULLUP = 2 } PinMode; +typedef enum _SpiSettings_ByteOrder { + SpiSettings_ByteOrder_MSBFIRST = 0, + SpiSettings_ByteOrder_LSBFIRST = 1 +} SpiSettings_ByteOrder; + +typedef enum _SpiSettings_DataMode { + SpiSettings_DataMode_SPI_MODE0 = 0, + SpiSettings_DataMode_SPI_MODE1 = 1, + SpiSettings_DataMode_SPI_MODE2 = 2, + SpiSettings_DataMode_SPI_MODE3 = 3 +} SpiSettings_DataMode; + typedef enum _HostedCommand_Version { HostedCommand_Version_HOSTED_V_1_0 = 0 } HostedCommand_Version; /* Struct definitions */ +typedef struct _RequestSpiEndTransaction { + char dummy_field; +} RequestSpiEndTransaction; + +typedef struct _RequestSpiTransfer { + pb_callback_t data; +} RequestSpiTransfer; + +typedef struct _RequestSpiWrite { + pb_callback_t data; +} RequestSpiWrite; + +typedef struct _ResponseSpiRead { + pb_callback_t data; +} ResponseSpiRead; + +typedef struct _ResponseSpiTransfer { + pb_callback_t data; +} ResponseSpiTransfer; + typedef struct _RequestDigitalRead { uint32_t pin; } RequestDigitalRead; @@ -39,10 +71,29 @@ typedef struct _RequestPinMode { PinMode mode; } RequestPinMode; +typedef struct _RequestSpiRead { + uint32_t length; +} RequestSpiRead; + typedef struct _ResponseDigitalRead { uint32_t value; } ResponseDigitalRead; +typedef struct _ResponseSpiWrite { + uint32_t length; +} ResponseSpiWrite; + +typedef struct _SpiSettings { + uint32_t speed; + SpiSettings_ByteOrder byteOrder; + SpiSettings_DataMode dataMode; +} SpiSettings; + +typedef struct _RequestSpiBeginTransaction { + bool has_settings; + SpiSettings settings; +} RequestSpiBeginTransaction; + typedef struct _HostedCommand { HostedCommand_Version version; pb_size_t which_payload; @@ -51,6 +102,14 @@ typedef struct _HostedCommand { RequestPinMode requestPinMode; RequestDigitalRead requestDigitalRead; ResponseDigitalRead responseDigitalRead; + RequestSpiBeginTransaction requestSpiBeginTransaction; + RequestSpiEndTransaction requestSpiEndTransaction; + RequestSpiTransfer requestSpiTransfer; + ResponseSpiTransfer responseSpiTransfer; + RequestSpiWrite requestSpiWrite; + ResponseSpiWrite responseSpiWrite; + RequestSpiRead requestSpiRead; + ResponseSpiRead responseSpiRead; } payload; } HostedCommand; @@ -60,6 +119,14 @@ typedef struct _HostedCommand { #define _PinMode_MAX PinMode_INPUT_PULLUP #define _PinMode_ARRAYSIZE ((PinMode)(PinMode_INPUT_PULLUP+1)) +#define _SpiSettings_ByteOrder_MIN SpiSettings_ByteOrder_MSBFIRST +#define _SpiSettings_ByteOrder_MAX SpiSettings_ByteOrder_LSBFIRST +#define _SpiSettings_ByteOrder_ARRAYSIZE ((SpiSettings_ByteOrder)(SpiSettings_ByteOrder_LSBFIRST+1)) + +#define _SpiSettings_DataMode_MIN SpiSettings_DataMode_SPI_MODE0 +#define _SpiSettings_DataMode_MAX SpiSettings_DataMode_SPI_MODE3 +#define _SpiSettings_DataMode_ARRAYSIZE ((SpiSettings_DataMode)(SpiSettings_DataMode_SPI_MODE3+1)) + #define _HostedCommand_Version_MIN HostedCommand_Version_HOSTED_V_1_0 #define _HostedCommand_Version_MAX HostedCommand_Version_HOSTED_V_1_0 #define _HostedCommand_Version_ARRAYSIZE ((HostedCommand_Version)(HostedCommand_Version_HOSTED_V_1_0+1)) @@ -70,25 +137,61 @@ typedef struct _HostedCommand { #define RequestPinMode_init_default {0, _PinMode_MIN} #define RequestDigitalRead_init_default {0} #define ResponseDigitalRead_init_default {0} +#define SpiSettings_init_default {0, _SpiSettings_ByteOrder_MIN, _SpiSettings_DataMode_MIN} +#define RequestSpiBeginTransaction_init_default {false, SpiSettings_init_default} +#define RequestSpiEndTransaction_init_default {0} +#define RequestSpiTransfer_init_default {{{NULL}, NULL}} +#define ResponseSpiTransfer_init_default {{{NULL}, NULL}} +#define RequestSpiWrite_init_default {{{NULL}, NULL}} +#define ResponseSpiWrite_init_default {0} +#define RequestSpiRead_init_default {0} +#define ResponseSpiRead_init_default {{{NULL}, NULL}} #define HostedCommand_init_default {_HostedCommand_Version_MIN, 0, {RequestDigitalWrite_init_default}} #define RequestDigitalWrite_init_zero {0, 0} #define RequestPinMode_init_zero {0, _PinMode_MIN} #define RequestDigitalRead_init_zero {0} #define ResponseDigitalRead_init_zero {0} +#define SpiSettings_init_zero {0, _SpiSettings_ByteOrder_MIN, _SpiSettings_DataMode_MIN} +#define RequestSpiBeginTransaction_init_zero {false, SpiSettings_init_zero} +#define RequestSpiEndTransaction_init_zero {0} +#define RequestSpiTransfer_init_zero {{{NULL}, NULL}} +#define ResponseSpiTransfer_init_zero {{{NULL}, NULL}} +#define RequestSpiWrite_init_zero {{{NULL}, NULL}} +#define ResponseSpiWrite_init_zero {0} +#define RequestSpiRead_init_zero {0} +#define ResponseSpiRead_init_zero {{{NULL}, NULL}} #define HostedCommand_init_zero {_HostedCommand_Version_MIN, 0, {RequestDigitalWrite_init_zero}} /* Field tags (for use in manual encoding/decoding) */ +#define RequestSpiTransfer_data_tag 1 +#define RequestSpiWrite_data_tag 1 +#define ResponseSpiRead_data_tag 1 +#define ResponseSpiTransfer_data_tag 1 #define RequestDigitalRead_pin_tag 1 #define RequestDigitalWrite_pin_tag 1 #define RequestDigitalWrite_value_tag 2 #define RequestPinMode_pin_tag 1 #define RequestPinMode_mode_tag 2 +#define RequestSpiRead_length_tag 1 #define ResponseDigitalRead_value_tag 1 +#define ResponseSpiWrite_length_tag 1 +#define SpiSettings_speed_tag 1 +#define SpiSettings_byteOrder_tag 2 +#define SpiSettings_dataMode_tag 3 +#define RequestSpiBeginTransaction_settings_tag 1 #define HostedCommand_version_tag 1 #define HostedCommand_requestDigitalWrite_tag 10 #define HostedCommand_requestPinMode_tag 11 #define HostedCommand_requestDigitalRead_tag 12 #define HostedCommand_responseDigitalRead_tag 13 +#define HostedCommand_requestSpiBeginTransaction_tag 14 +#define HostedCommand_requestSpiEndTransaction_tag 15 +#define HostedCommand_requestSpiTransfer_tag 16 +#define HostedCommand_responseSpiTransfer_tag 17 +#define HostedCommand_requestSpiWrite_tag 18 +#define HostedCommand_responseSpiWrite_tag 19 +#define HostedCommand_requestSpiRead_tag 20 +#define HostedCommand_responseSpiRead_tag 21 /* Struct field encoding specification for nanopb */ #define RequestDigitalWrite_FIELDLIST(X, a) \ @@ -113,23 +216,96 @@ X(a, STATIC, SINGULAR, UINT32, value, 1) #define ResponseDigitalRead_CALLBACK NULL #define ResponseDigitalRead_DEFAULT NULL +#define SpiSettings_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, speed, 1) \ +X(a, STATIC, SINGULAR, UENUM, byteOrder, 2) \ +X(a, STATIC, SINGULAR, UENUM, dataMode, 3) +#define SpiSettings_CALLBACK NULL +#define SpiSettings_DEFAULT NULL + +#define RequestSpiBeginTransaction_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, settings, 1) +#define RequestSpiBeginTransaction_CALLBACK NULL +#define RequestSpiBeginTransaction_DEFAULT NULL +#define RequestSpiBeginTransaction_settings_MSGTYPE SpiSettings + +#define RequestSpiEndTransaction_FIELDLIST(X, a) \ + +#define RequestSpiEndTransaction_CALLBACK NULL +#define RequestSpiEndTransaction_DEFAULT NULL + +#define RequestSpiTransfer_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, data, 1) +#define RequestSpiTransfer_CALLBACK pb_default_field_callback +#define RequestSpiTransfer_DEFAULT NULL + +#define ResponseSpiTransfer_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, data, 1) +#define ResponseSpiTransfer_CALLBACK pb_default_field_callback +#define ResponseSpiTransfer_DEFAULT NULL + +#define RequestSpiWrite_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, data, 1) +#define RequestSpiWrite_CALLBACK pb_default_field_callback +#define RequestSpiWrite_DEFAULT NULL + +#define ResponseSpiWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, length, 1) +#define ResponseSpiWrite_CALLBACK NULL +#define ResponseSpiWrite_DEFAULT NULL + +#define RequestSpiRead_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, length, 1) +#define RequestSpiRead_CALLBACK NULL +#define RequestSpiRead_DEFAULT NULL + +#define ResponseSpiRead_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, data, 1) +#define ResponseSpiRead_CALLBACK pb_default_field_callback +#define ResponseSpiRead_DEFAULT NULL + #define HostedCommand_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, version, 1) \ X(a, STATIC, ONEOF, MESSAGE, (payload,requestDigitalWrite,payload.requestDigitalWrite), 10) \ X(a, STATIC, ONEOF, MESSAGE, (payload,requestPinMode,payload.requestPinMode), 11) \ X(a, STATIC, ONEOF, MESSAGE, (payload,requestDigitalRead,payload.requestDigitalRead), 12) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,responseDigitalRead,payload.responseDigitalRead), 13) +X(a, STATIC, ONEOF, MESSAGE, (payload,responseDigitalRead,payload.responseDigitalRead), 13) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,requestSpiBeginTransaction,payload.requestSpiBeginTransaction), 14) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,requestSpiEndTransaction,payload.requestSpiEndTransaction), 15) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,requestSpiTransfer,payload.requestSpiTransfer), 16) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,responseSpiTransfer,payload.responseSpiTransfer), 17) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,requestSpiWrite,payload.requestSpiWrite), 18) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,responseSpiWrite,payload.responseSpiWrite), 19) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,requestSpiRead,payload.requestSpiRead), 20) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,responseSpiRead,payload.responseSpiRead), 21) #define HostedCommand_CALLBACK NULL #define HostedCommand_DEFAULT NULL #define HostedCommand_payload_requestDigitalWrite_MSGTYPE RequestDigitalWrite #define HostedCommand_payload_requestPinMode_MSGTYPE RequestPinMode #define HostedCommand_payload_requestDigitalRead_MSGTYPE RequestDigitalRead #define HostedCommand_payload_responseDigitalRead_MSGTYPE ResponseDigitalRead +#define HostedCommand_payload_requestSpiBeginTransaction_MSGTYPE RequestSpiBeginTransaction +#define HostedCommand_payload_requestSpiEndTransaction_MSGTYPE RequestSpiEndTransaction +#define HostedCommand_payload_requestSpiTransfer_MSGTYPE RequestSpiTransfer +#define HostedCommand_payload_responseSpiTransfer_MSGTYPE ResponseSpiTransfer +#define HostedCommand_payload_requestSpiWrite_MSGTYPE RequestSpiWrite +#define HostedCommand_payload_responseSpiWrite_MSGTYPE ResponseSpiWrite +#define HostedCommand_payload_requestSpiRead_MSGTYPE RequestSpiRead +#define HostedCommand_payload_responseSpiRead_MSGTYPE ResponseSpiRead extern const pb_msgdesc_t RequestDigitalWrite_msg; extern const pb_msgdesc_t RequestPinMode_msg; extern const pb_msgdesc_t RequestDigitalRead_msg; extern const pb_msgdesc_t ResponseDigitalRead_msg; +extern const pb_msgdesc_t SpiSettings_msg; +extern const pb_msgdesc_t RequestSpiBeginTransaction_msg; +extern const pb_msgdesc_t RequestSpiEndTransaction_msg; +extern const pb_msgdesc_t RequestSpiTransfer_msg; +extern const pb_msgdesc_t ResponseSpiTransfer_msg; +extern const pb_msgdesc_t RequestSpiWrite_msg; +extern const pb_msgdesc_t ResponseSpiWrite_msg; +extern const pb_msgdesc_t RequestSpiRead_msg; +extern const pb_msgdesc_t ResponseSpiRead_msg; extern const pb_msgdesc_t HostedCommand_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ @@ -137,6 +313,15 @@ extern const pb_msgdesc_t HostedCommand_msg; #define RequestPinMode_fields &RequestPinMode_msg #define RequestDigitalRead_fields &RequestDigitalRead_msg #define ResponseDigitalRead_fields &ResponseDigitalRead_msg +#define SpiSettings_fields &SpiSettings_msg +#define RequestSpiBeginTransaction_fields &RequestSpiBeginTransaction_msg +#define RequestSpiEndTransaction_fields &RequestSpiEndTransaction_msg +#define RequestSpiTransfer_fields &RequestSpiTransfer_msg +#define ResponseSpiTransfer_fields &ResponseSpiTransfer_msg +#define RequestSpiWrite_fields &RequestSpiWrite_msg +#define ResponseSpiWrite_fields &ResponseSpiWrite_msg +#define RequestSpiRead_fields &RequestSpiRead_msg +#define ResponseSpiRead_fields &ResponseSpiRead_msg #define HostedCommand_fields &HostedCommand_msg /* Maximum encoded size of messages (where known) */ @@ -144,7 +329,16 @@ extern const pb_msgdesc_t HostedCommand_msg; #define RequestPinMode_size 8 #define RequestDigitalRead_size 6 #define ResponseDigitalRead_size 6 -#define HostedCommand_size 16 +#define SpiSettings_size 10 +#define RequestSpiBeginTransaction_size 12 +#define RequestSpiEndTransaction_size 0 +/* RequestSpiTransfer_size depends on runtime parameters */ +/* ResponseSpiTransfer_size depends on runtime parameters */ +/* RequestSpiWrite_size depends on runtime parameters */ +#define ResponseSpiWrite_size 6 +#define RequestSpiRead_size 6 +/* ResponseSpiRead_size depends on runtime parameters */ +/* HostedCommand_size depends on runtime parameters */ #ifdef __cplusplus } /* extern "C" */ diff --git a/Sming/Components/Hosted/proto/hosted.proto b/Sming/Components/Hosted/proto/hosted.proto index f811861745..9897bb43ba 100644 --- a/Sming/Components/Hosted/proto/hosted.proto +++ b/Sming/Components/Hosted/proto/hosted.proto @@ -25,6 +25,60 @@ message ResponseDigitalRead { uint32 value = 1; } +message SpiSettings { + uint32 speed = 1; + enum ByteOrder { + MSBFIRST = 0; + LSBFIRST = 1; + } + ByteOrder byteOrder = 2; + enum DataMode { + SPI_MODE0 = 0; + SPI_MODE1 = 1; + SPI_MODE2 = 2; + SPI_MODE3 = 3; + } + DataMode dataMode = 3; +} + +message RequestSpiBeginTransaction +{ + SpiSettings settings = 1; +} + +message RequestSpiEndTransaction +{ + +} + +message RequestSpiTransfer { + bytes data = 1; +} + +message ResponseSpiTransfer { + bytes data = 1; +} + +message RequestSpiWrite +{ + bytes data = 1; +} + +message ResponseSpiWrite +{ + uint32 length = 1; +} + +message RequestSpiRead +{ + uint32 length = 1; +} + +message ResponseSpiRead +{ + bytes data = 1; +} + message HostedCommand { // Version of the protocol for future compatibility enum Version { @@ -36,5 +90,13 @@ message HostedCommand { RequestPinMode requestPinMode = 11; RequestDigitalRead requestDigitalRead = 12; ResponseDigitalRead responseDigitalRead = 13; + RequestSpiBeginTransaction requestSpiBeginTransaction = 14; + RequestSpiEndTransaction requestSpiEndTransaction = 15; + RequestSpiTransfer requestSpiTransfer = 16; + ResponseSpiTransfer responseSpiTransfer = 17; + RequestSpiWrite requestSpiWrite = 18; + ResponseSpiWrite responseSpiWrite = 19; + RequestSpiRead requestSpiRead = 20; + ResponseSpiRead responseSpiRead = 21; } } diff --git a/Sming/Components/Hosted/src/HostedCommon.h b/Sming/Components/Hosted/src/HostedCommon.h index 363fb72bec..b4ebd42d71 100644 --- a/Sming/Components/Hosted/src/HostedCommon.h +++ b/Sming/Components/Hosted/src/HostedCommon.h @@ -4,6 +4,7 @@ #include #include #include "hosted.pb.h" +#include "HostedUtils.h" constexpr int HOSTED_OK = 0; constexpr int HOSTED_FAIL = -1; @@ -24,6 +25,8 @@ class HostedCommon { public: virtual bool onData(const char* at, size_t length) = 0; - + virtual ~HostedCommon() + { + } private: }; diff --git a/Sming/Components/Hosted/src/HostedServer.h b/Sming/Components/Hosted/src/HostedServer.h index 99edee9eaa..743ed8cac3 100644 --- a/Sming/Components/Hosted/src/HostedServer.h +++ b/Sming/Components/Hosted/src/HostedServer.h @@ -35,6 +35,8 @@ class HostedServer HostedCommand request = HostedCommand_init_zero; HostedCommand response = HostedCommand_init_zero; + request.payload.requestSpiTransfer.data.funcs.decode = &pbDecodeData; + if (at == nullptr || length < 0) { debug_e("empty buffer"); return HOSTED_FAIL; @@ -76,6 +78,9 @@ class HostedServer result = HOSTED_FAIL; break; } + + // TODO: cleanup + } while(input.bytes_left && success); return result; diff --git a/Sming/Components/Hosted/src/HostedUtils.cpp b/Sming/Components/Hosted/src/HostedUtils.cpp new file mode 100644 index 0000000000..2279e2c204 --- /dev/null +++ b/Sming/Components/Hosted/src/HostedUtils.cpp @@ -0,0 +1,42 @@ +#include "HostedUtils.h" +#include + +// See: https://iam777.tistory.com/538 + +bool pbEncodeData(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + PbData *data = (PbData*) *arg; + if(data == nullptr) { + return false; + } + + if (!pb_encode_tag_for_field(stream, field)) { + return false; + } + + return pb_encode_string(stream, (uint8_t*)data->value, data->length); +} + +bool pbDecodeData(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + uint8_t buffer[1024] = {0}; + + /* We could read block-by-block to avoid the large buffer... */ + if (stream->bytes_left > sizeof(buffer) - 1) { + return false; + } + + size_t available = stream->bytes_left; + if (!pb_read(stream, buffer, stream->bytes_left)) { + return false; + } + + + MemoryDataStream* data = (MemoryDataStream*) *arg; + if(data == nullptr) { + data = new MemoryDataStream(); + *arg = (void*)data; + } + data->write(buffer, available); + return true; +} diff --git a/Sming/Components/Hosted/src/HostedUtils.h b/Sming/Components/Hosted/src/HostedUtils.h new file mode 100644 index 0000000000..e4436e35e2 --- /dev/null +++ b/Sming/Components/Hosted/src/HostedUtils.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include "hosted.pb.h" + +typedef struct { + uint8_t* value; + size_t length; +} PbData; + +bool pbEncodeData(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); +bool pbDecodeData(pb_istream_t *stream, const pb_field_t *field, void **arg);