commit 17bbec9c96585a9f9f749f96e7f9b61b2268b509 Author: cfif Date: Mon Jun 2 13:26:40 2025 +0300 Init diff --git a/Inc/XfcArray.h b/Inc/XfcArray.h new file mode 100644 index 0000000..bc2c164 --- /dev/null +++ b/Inc/XfcArray.h @@ -0,0 +1,49 @@ +// +// Created by xemon on 20.04.2022. +// + +#ifndef XfcArray_H +#define XfcArray_H + +#include "stdint.h" +#include "stdbool.h" + +typedef struct { + uint8_t *data; + uint16_t begin; + uint16_t end; + uint16_t limit; +} tXfcArray; + + +#define XfcArrayCreateStatic(NAME, LENGTH) \ +uint8_t NAME##_Data[LENGTH]; \ +XfcArray NAME = { .data = NAME##_Data, .begin= 0, .end = 0, .limit = sizeof(NAME##_Data)}; + +void XfcArrayInit(tXfcArray *array, uint8_t *memAlloc, uint16_t limit); + +#define XfcArrayInitStatic(ENV, MEM) XfcArrayInit(ENV,MEM,sizeof(MEM)) + +void XfcArrayClear(tXfcArray *array); + +bool XfcArrayNotFull(tXfcArray *array); + +uint16_t XfcArrayGetDataSize(tXfcArray *array); + +uint8_t *XfcGetTail(tXfcArray *array); + +bool XfcArrayAddByte(tXfcArray *array, uint8_t value); + +uint16_t XfcArrayAddBytes(tXfcArray *array, uint8_t *bytes, uint16_t length); + +uint16_t XfcArrayAddLength(tXfcArray *array, uint16_t length); + +uint16_t XfcArrayGetSpace(tXfcArray *array); + +uint16_t XfcArrayGetBytesFront(tXfcArray *array, uint8_t *bytes, uint16_t length); + +void XfcArrayRemoveBytesFront(tXfcArray *env, uint16_t count); + +void XfcArraySpaceInv(tXfcArray *array); + +#endif //XfcArray_H diff --git a/Inc/XfcCounting.h b/Inc/XfcCounting.h new file mode 100644 index 0000000..c44b015 --- /dev/null +++ b/Inc/XfcCounting.h @@ -0,0 +1,19 @@ +// +// Created by xemon on 20.04.2022. +// + +#ifndef XFC_COUNTING_H +#define XFC_COUNTING_H + + +#define COUNTER_INC(COUNTER) ++COUNTER; +#define COUNTER_ADD(COUNTER, VALUE) COUNTER += VALUE; +#define COUNTER_ADD_IF(EXPRESION, COUNTER, VALUE) if(EXPRESION){COUNTER += VALUE;} + +#define ENV_COUNTER_INC(COUNTER) COUNTER_INC(env->counters.COUNTER) +#define ENV_COUNTER_ADD(COUNTER, VALUE) COUNTER_ADD(env->counters.COUNTER, VALUE) +#define ENV_COUNTER_ADD_IF(EXPRESION, COUNTER, VALUE) COUNTER_ADD_IF(EXPRESION, env->counters.COUNTER, VALUE) + +#define COUNTER_RESET(COUNTER) COUNTER = 0; + +#endif //XFC_COUNTING_H diff --git a/Inc/XfcProtCommon.h b/Inc/XfcProtCommon.h new file mode 100644 index 0000000..7c9d61f --- /dev/null +++ b/Inc/XfcProtCommon.h @@ -0,0 +1,30 @@ +// +// Created by cfif on 11.10.22. +// + +#ifndef UVEOS_ON_NATION_XFCTRANSPACKCOMMON_H +#define UVEOS_ON_NATION_XFCTRANSPACKCOMMON_H + +#include "stdint.h" + + +#define XFC_TRANSPORT_HEADER_LEN 5 +#define XFC_TRANSPORT_COMMAND_ID_OFFSET 1 +#define XFC_TRANSPORT_DATA_LEN_OFFSET 3 +#define XFC_TRANSPORT_CRC_LEN 2 + + +typedef struct { + uint8_t request; + uint8_t response; +} tXfcProtMagicNumbers; + +extern const tXfcProtMagicNumbers XFC_STD_MAGIC_NUMBERS; + + +////Mandatory request codes +//const uint16_t XFC_PROT_CMD_CODE_NULL = 0x0; +//const uint16_t XFC_PROT_CMD_CODE_PING = 0x1; +//const uint16_t XFC_PROT_CMD_CMD_TABLE = 0x2; + +#endif //UVEOS_ON_NATION_XFCTRANSPACKCOMMON_H diff --git a/Inc/XfcProtCrc.h b/Inc/XfcProtCrc.h new file mode 100644 index 0000000..c589c6a --- /dev/null +++ b/Inc/XfcProtCrc.h @@ -0,0 +1,12 @@ +// +// Created by xemon on 05.05.2022. +// + +#ifndef XFCTRANSPACKCRC_H +#define XFCTRANSPACKCRC_H + +#include "stdint.h" + +uint16_t XfcProtCrc(uint8_t *data, uint16_t length); + +#endif //XFCTRANSPACKCRC_H diff --git a/Inc/XfcProtDecoder.h b/Inc/XfcProtDecoder.h new file mode 100644 index 0000000..07f6ea3 --- /dev/null +++ b/Inc/XfcProtDecoder.h @@ -0,0 +1,36 @@ +// +// Created by xemon on 05.05.2022. +// + +#ifndef XFCTRANSPORTPACKETPARSER_H +#define XFCTRANSPORTPACKETPARSER_H + +#include "stdint.h" +#include "stdbool.h" +#include "XfcArray.h" + +typedef struct { + uint8_t magic; + tXfcArray *buffer; +} tXfcProtDecoder; + +uint16_t XfcTransPackDecoderNextMagicFrom(tXfcProtDecoder *env, uint16_t begin); + +bool XfcTransPackDecoderIsStartsWithMagick(tXfcProtDecoder *env); + +bool XfcTransPackDecoderHasHeader(tXfcProtDecoder *env); + +uint16_t XfcTransPackDecoderGetId(tXfcProtDecoder *env); + +uint16_t XfcTransPackDecoderGetDataSegmentLength(tXfcProtDecoder *env); + +uint16_t XfcTransPackDecoderGetRequiredFullPackLength(tXfcProtDecoder *env); + +bool XfcTransPackDecoderHasRequiredLength(tXfcProtDecoder *env); + +bool XfcTransPackDecoderIsCrcCorrect(tXfcProtDecoder *env); + +tXfcArray XfcTransPackDecoderGetDataSegmentAsArray(tXfcProtDecoder *env); + + +#endif //XFCTRANSPORTPACKETPARSER_H diff --git a/Inc/XfcProtEncoder.h b/Inc/XfcProtEncoder.h new file mode 100644 index 0000000..a546df0 --- /dev/null +++ b/Inc/XfcProtEncoder.h @@ -0,0 +1,25 @@ +// +// Created by xemon on 05.05.2022. +// + +#ifndef PDM_FIR_TEST_XFCTRANSPACKENCODER_H +#define PDM_FIR_TEST_XFCTRANSPACKENCODER_H + +#include "stdint.h" +#include "stdbool.h" +#include "XfcArray.h" + +typedef struct { + uint8_t magic; + tXfcArray *buffer; +} tXfcProtEncoder; + +tXfcArray XfcTransPackEncoderGetDataSegmentAsArray(tXfcProtEncoder *env); + +void XfcTransPackEncoderSetId(tXfcProtEncoder *env, uint16_t id); + +void XfcTransPackEncoderSetDataSegmentLength(tXfcProtEncoder *env, uint16_t dataSegmentLength); + +void XfcTransPackEncoderFinalizeAndSignCrc(tXfcProtEncoder *env); + +#endif //PDM_FIR_TEST_XFCTRANSPACKENCODER_H diff --git a/Inc/XfcProtListener.h b/Inc/XfcProtListener.h new file mode 100644 index 0000000..f8cc522 --- /dev/null +++ b/Inc/XfcProtListener.h @@ -0,0 +1,58 @@ +// +// Created by xemon on 05.05.2022. +// + +#ifndef PDM_FIR_TEST_XFCTRANSPACKLISTNER_H +#define PDM_FIR_TEST_XFCTRANSPACKLISTNER_H + +#define XFC_COMINT_COUNTING + +#include "XfcCounting.h" +#include "XfcProtDecoder.h" +#include "XfcProtProcessor.h" +#include "XfcProtTable.h" + + +typedef struct { + +#ifdef XFC_COMINT_COUNTING + struct { + uint32_t rx; + uint32_t rx_skip; + } counters; +#endif + + void *commonArgs; + + tXfcProtDecoder requestDecoder; + tXfcArray requestBuffer; + + tXfcProtTable *processors; + +} tXfcProtListener; + +//Этот вид обработчика слушает комманды во входном потоке данных +//находит обработчик по id, выполняет его, но ответ не посылает (в отличии от Respondent) +void XfcProtListener_Init( + tXfcProtListener *env, + + void *commonArgs, + tXfcProtTable *processors, + + tXfcArray requestBuffer, + uint8_t requestMagic +); + +bool XfcProtListener_Step(tXfcProtListener *env); + +void XfcProtListener_SkipCurrentRequest(tXfcProtListener *env); + +void XfcProtListener_AddBytes(tXfcProtListener *env, uint8_t *bytes, uint16_t size); + +bool XfcProtListener_isValidHeader(tXfcProtListener *env); + +bool XfcProtListener_HasPacket(tXfcProtListener *env); + +void XfcProtListener_SkipToNextMagic(tXfcProtListener *env, uint16_t begin); + +#endif //PDM_FIR_TEST_XFCTRANSPACKLISTNER_H diff --git a/Inc/XfcProtProcessor.h b/Inc/XfcProtProcessor.h new file mode 100644 index 0000000..5dd4349 --- /dev/null +++ b/Inc/XfcProtProcessor.h @@ -0,0 +1,19 @@ +// +// Created by xemon on 05.05.2022. +// + +#ifndef XFCTRANSPACKPROCESSOR_H +#define XFCTRANSPACKPROCESSOR_H + +#include "XfcArray.h" + +typedef uint8_t (*tXfcProtMethod)(tXfcArray *requestData, tXfcArray *responseData, void *sub); + +typedef struct { + char *textId; + uint8_t textIdLen; + void *args; + tXfcProtMethod process; +} tXfcProtProcessor; + +#endif //XFCTRANSPACKPROCESSOR_H diff --git a/Inc/XfcProtProcessorUtilDefines.h b/Inc/XfcProtProcessorUtilDefines.h new file mode 100644 index 0000000..b8c7c34 --- /dev/null +++ b/Inc/XfcProtProcessorUtilDefines.h @@ -0,0 +1,49 @@ +// +// Created by xemon on 21.04.2022. +// + +#ifndef XFCTRANSPORTPROTOCOLPROCESSORDEFINES_H +#define XFCTRANSPORTPROTOCOLPROCESSORDEFINES_H + +#include +#include "XfcProtProcessor.h" +#include +#include "stddef.h" + +////Defines for read/write operations inside Packet Processor + +//#define XFC_CMD_TX_SET_CODE(CODE) *response->fields.id = CODE; + +#define XFC_CMD_TX_OVERFLOW() return XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_CMD_OVERFLOW; +#define XFC_CMD_RX_CUTOFF() return XFC_TRANSPORT_PROTOCOL_REQUEST_UNEXPECTEDLY_SHORT; + +#define XFC_CMD_TX_ADD_WITH_OVERFLOW_CHECK(DATA, LEN) \ +if(XfcArrayAddBytes(response,DATA, LEN)!=LEN){ XFC_CMD_TX_OVERFLOW()}; + + +#define XFC_CMD_RX_GET_WITH_CUTOFF_CHECK(DATA, LEN) \ +if(XfcArrayGetBytesFront(request,DATA, LEN)!=LEN){ XFC_CMD_RX_CUTOFF()}; + + +#define XFC_CMD_TX_ADD_STR(str) XFC_CMD_TX_ADD_WITH_OVERFLOW_CHECK((uint8_t*)str, sizeof(str)-1) +#define XFC_CMD_TX_ADD_STROBJ(str) XFC_CMD_TX_ADD_WITH_OVERFLOW_CHECK(str->data, str->length) +#define XFC_CMD_TX_ADD_RAW(obj) XFC_CMD_TX_ADD_WITH_OVERFLOW_CHECK((uint8_t*)&obj, sizeof(obj)) +#define XFC_CMD_TX_ADD_ARR(arr, len) XFC_CMD_TX_ADD_WITH_OVERFLOW_CHECK((uint8_t*)arr, len) + +#define XFC_CMD_TX_ADD_STRLINK(str) XFC_CMD_TX_ADD_RAW( *(str).length) XFC_CMD_TX_ADD_ARR((str).data, *(str).length) + + +#define XFC_CMD_TX_ADD_PSTR(str) {uint8_t len = sizeof(str)-1; XFC_CMD_TX_ADD_RAW(len); XFC_CMD_TX_ADD_STR(str);} + + +#define XFC_CMD_RX_GET_STR(str) XFC_CMD_RX_GET_WITH_CUTOFF_CHECK((uint8_t*)str, sizeof(str)) +#define XFC_CMD_RX_GET_RAW(obj) XFC_CMD_RX_GET_WITH_CUTOFF_CHECK((uint8_t*)&obj, sizeof(obj)) +#define XFC_CMD_RX_GET_ARR(arr, len) XFC_CMD_RX_GET_WITH_CUTOFF_CHECK((uint8_t*)arr, len) + + + +//XFC_REQUEST_PROCESSOR_DIRECT +#define XFC_REQPROC_DIR(CODE, METHOD) [CODE]={.id=CODE, .process=METHOD} + + +#endif //XFCTRANSPORTPROTOCOLPROCESSORDEFINES_H diff --git a/Inc/XfcProtRequester.h b/Inc/XfcProtRequester.h new file mode 100644 index 0000000..e73ccd0 --- /dev/null +++ b/Inc/XfcProtRequester.h @@ -0,0 +1,63 @@ +// +// Created by xemon on 07.11.23. +// + +#ifndef MOTOTERMINAL_MAIN_ONAT435_XFCPROTREQUESTER_H +#define MOTOTERMINAL_MAIN_ONAT435_XFCPROTREQUESTER_H + +#include "XfcProtDecoder.h" +#include "XfcProtEncoder.h" +#include "XfcProtResponseCodes.h" +#include "SerialPortIO.h" +#include "XfcProtCommon.h" + +typedef enum { + eXfcProtRequesterStatus_OK = 0, + eXfcProtRequesterStatus_UNKNOWN_ERROR, + eXfcProtRequesterStatus_REQUEST_BUILD_OVERFLOW, + eXfcProtRequesterStatus_TRANSMIT_ERROR, + eXfcProtRequesterStatus_RECIVE_BUFFER_OVERFLOW, + eXfcProtRequesterStatus_PREFIX_MISMATCH, + eXfcProtRequesterStatus_CRC_ERROR, + eXfcProtRequesterStatus_RECIVE_TIMEOUT, + eXfcProtRequesterStatus_RESPONSE_SHORT, + eXfcProtRequesterStatus_BUILD_EXECUTION_ERROR, + eXfcProtRequesterStatus_PARSING_EXECUTION_ERROR, +} eXfcProtRequesterStatus; + +typedef tXfcTransportProtocolResponseCode (*tXfcRequesterMethod)(void *env, tXfcArray *request); + +typedef struct { + + tSerialPortIO *io; + + tXfcProtDecoder decoder; + tXfcProtEncoder encoder; + + tXfcArray requestBuffer; + tXfcArray responseBuffer; + + int32_t transmitTimeout; + +} tXfcProtRequester; + + +void XfcProtRequester_init( + tXfcProtRequester *env, + + tSerialPortIO *io, + + tXfcArray requestBuffer, + tXfcArray responseBuffer, + + tXfcProtMagicNumbers magicNumbers +); + +eXfcProtRequesterStatus XfcProtRequester_makeRequest( + tXfcProtRequester *env, uint16_t id, + void *builder, tXfcRequesterMethod buildMethod, + void *parser, tXfcRequesterMethod parseMethod, + int32_t timeout +); + +#endif //MOTOTERMINAL_MAIN_ONAT435_XFCPROTREQUESTER_H diff --git a/Inc/XfcProtRespondent.h b/Inc/XfcProtRespondent.h new file mode 100644 index 0000000..da30091 --- /dev/null +++ b/Inc/XfcProtRespondent.h @@ -0,0 +1,60 @@ +// +// Created by xemon on 05.05.2022. +// + +#ifndef PDM_FIR_TEST_XFCTRANSPACKRESPONSER_H +#define PDM_FIR_TEST_XFCTRANSPACKRESPONSER_H + +#define XFC_COMINT_COUNTING + +#include "XfcCounting.h" +#include "XfcProtDecoder.h" +#include "XfcProtProcessor.h" +#include "XfcProtEncoder.h" +#include "XfcProtTable.h" +#include "XfcProtCommon.h" + + +typedef struct { + +#ifdef XFC_COMINT_COUNTING + struct { + uint32_t rx; + uint32_t tx; + uint32_t rx_skip; + uint32_t tx_skip; + } counters; +#endif + + void *commonArgs; + + tXfcProtDecoder requestDecoder; + tXfcProtEncoder responseEncoder; + + tXfcArray requestBuffer; + tXfcArray responseBuffer; + + tXfcProtTable *processors; +} tXfcProtRespondent; + +//Этот вид обработчика слушает комманды во входном потоке данных +//находит обработчик по id, и возвращает ответ (в отличии от Listener) +void XfcProtRespondent_Init( + tXfcProtRespondent *env, + + void *commonArgs, + tXfcProtTable *processors, + + tXfcArray requestBuffer, + tXfcArray responseBuffer, + + tXfcProtMagicNumbers magicNumbers +); + +bool XfcProtRespondent_Step(tXfcProtRespondent *env); + +void XfcProtRespondent_SkipCurrentRequest(tXfcProtRespondent *env); + +void XfcProtRespondent_AddBytes(tXfcProtRespondent *env, uint8_t *bytes, uint16_t size); + +#endif //PDM_FIR_TEST_XFCTRANSPACKRESPONSER_H diff --git a/Inc/XfcProtResponseCodes.h b/Inc/XfcProtResponseCodes.h new file mode 100644 index 0000000..48ee895 --- /dev/null +++ b/Inc/XfcProtResponseCodes.h @@ -0,0 +1,16 @@ +// +// Created by xemon on 21.04.2022. +// + +#ifndef XFCTRANSPORTPROTOCOLRESPONSECODES_H +#define XFCTRANSPORTPROTOCOLRESPONSECODES_H + +typedef enum { + XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_OK = 0x01, + XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_EXECUTION_ERROR = 0x02, + XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_CMD_UNKNOWN = 0x03, + XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_CMD_OVERFLOW = 0x04, + XFC_TRANSPORT_PROTOCOL_REQUEST_UNEXPECTEDLY_SHORT = 0x05, +} tXfcTransportProtocolResponseCode; + +#endif //XFCTRANSPORTPROTOCOLRESPONSECODES_H diff --git a/Inc/XfcProtTable.h b/Inc/XfcProtTable.h new file mode 100644 index 0000000..5e4157f --- /dev/null +++ b/Inc/XfcProtTable.h @@ -0,0 +1,33 @@ +// +// Created by xemon on 01.11.22. +// + +#ifndef XFC_TRANSPORT_PROTOCOL_XFCPROTTABLE_H +#define XFC_TRANSPORT_PROTOCOL_XFCPROTTABLE_H + +#include "XfcProtProcessor.h" + +typedef struct { + tXfcProtProcessor *items; + uint16_t count; + uint16_t limit; +} tXfcProtTable; + +void XfcProtTable_Init(tXfcProtTable *env, tXfcProtProcessor *allocatedMem, uint16_t memLimit); + +#define XfcProtTable_InitStatic(ENV, MEM) XfcProtTable_Init(ENV,MEM, sizeof(MEM) / sizeof(tXfcProtProcessor)) + +bool XfcProtTable_Add( + tXfcProtTable *env, + char *staticStringTextId, + uint8_t textIdLen, + tXfcProtMethod method, + void *args +); + +#define XfcProtTable_AddStatic(ENV, TEXT_ID, METHOD, ARGS) XfcProtTable_Add(ENV, TEXT_ID,sizeof(TEXT_ID)-1,(tXfcProtMethod)METHOD, ARGS) + +tXfcProtProcessor *XfcProtTable_GetForId(tXfcProtTable *env, uint16_t id); + + +#endif //XFC_TRANSPORT_PROTOCOL_XFCPROTTABLE_H diff --git a/Src/XfcArray.c b/Src/XfcArray.c new file mode 100644 index 0000000..22c6125 --- /dev/null +++ b/Src/XfcArray.c @@ -0,0 +1,126 @@ +// +// Created by xemon on 20.04.2022. +// +#include +#include "XfcArray.h" + +void XfcArrayInit(tXfcArray *array, uint8_t *memAlloc, uint16_t limit) { + array->limit = limit; + array->data = memAlloc; + array->end = 0; + array->begin = 0; +} + +void XfcArrayClear(tXfcArray *array) { + array->end = 0; + array->begin = 0; +} + +bool XfcArrayNotFull(tXfcArray *array) { + return array->end < array->limit; +} + + +uint16_t XfcArrayGetDataSize(tXfcArray *array) { + if (array->begin >= array->end) { + return 0; + } + + return array->end - array->begin; +} + +uint8_t *XfcGetTail(tXfcArray *array) { + return array->data + array->end; +} + +uint16_t XfcArrayGetSpace(tXfcArray *array) { + if (array->limit <= array->end) { + return 0; + } + + return array->limit - array->end; +} + +uint16_t XfcArrayGetAvailable(tXfcArray *array) { + if (array->limit <= array->end) { + return 0; + } + + return array->limit - array->end; +} + + +bool XfcArrayAddByte(tXfcArray *array, uint8_t value) { + if (XfcArrayNotFull(array)) { + array->data[array->end] = value; + ++array->end; + return true; + } else { + return false; + } +} + +uint16_t XfcArrayAddLength(tXfcArray *array, uint16_t length) { + + uint16_t space = XfcArrayGetSpace(array); + + uint16_t toAdd = space > length ? length : space; + + array->end += toAdd; + + return toAdd; +} + +uint16_t XfcArrayAddBytes(tXfcArray *array, uint8_t *bytes, uint16_t length) { + + uint16_t space = XfcArrayGetSpace(array); + + uint16_t toAdd = space > length ? length : space; + + memcpy(array->data + array->end, bytes, toAdd); + + array->end += toAdd; + + return toAdd; +} + +void XfcArraySpaceInv(tXfcArray *array) { + if (array->begin == array->end) { + array->begin = array->end = 0; + } +} + +// +//void XfcArraySpaceInvForce(XfcArray *array) { +// if (array->begin == array->end) { +// array->begin = array->end = 0; +// } +//} + +uint16_t XfcArrayGetBytesFront(tXfcArray *array, uint8_t *bytes, uint16_t length) { + + uint16_t available = XfcArrayGetDataSize(array); + + uint16_t toGet = available > length ? length : available; + + memcpy(bytes, array->data + array->begin, toGet); + + array->begin += toGet; + + XfcArraySpaceInv(array); + + return toGet; +} + + +void XfcArrayRemoveBytesFront(tXfcArray *env, uint16_t count) { + uint16_t left = XfcArrayGetDataSize(env) - count; + + if (left) { + memmove(env->data, env->data + env->begin + count, left); + env->begin = 0; + env->end = left; + } else { + XfcArrayClear(env); + } +} diff --git a/Src/XfcCommon.c b/Src/XfcCommon.c new file mode 100644 index 0000000..d758b7a --- /dev/null +++ b/Src/XfcCommon.c @@ -0,0 +1,10 @@ +// +// Created by xemon on 05.05.2022. +// + +#include "XfcProtCommon.h" + +const tXfcProtMagicNumbers XFC_STD_MAGIC_NUMBERS = { + .request = 0x31, + .response = 0x3E, +}; \ No newline at end of file diff --git a/Src/XfcProtCrc.c b/Src/XfcProtCrc.c new file mode 100644 index 0000000..f3e6edc --- /dev/null +++ b/Src/XfcProtCrc.c @@ -0,0 +1,17 @@ +// +// Created by xemon on 05.05.2022. +// + + +#include "XfcProtCrc.h" + +uint16_t XfcProtCrc(uint8_t *data, uint16_t length) { + uint16_t src = 0; + + uint8_t *end = data + length; + + for (; data < end; ++data) { + src += *data; + } + return src; +} \ No newline at end of file diff --git a/Src/XfcProtDecoder.c b/Src/XfcProtDecoder.c new file mode 100644 index 0000000..bc845ee --- /dev/null +++ b/Src/XfcProtDecoder.c @@ -0,0 +1,65 @@ +// +// Created by xemon on 05.05.2022. +// + +#include "XfcProtDecoder.h" +#include "XfcProtCrc.h" +#include "XfcProtCommon.h" + + +uint16_t XfcTransPackDecoderNextMagicFrom(tXfcProtDecoder *env, uint16_t begin) { + + for (uint8_t *end = env->buffer->data + env->buffer->end, *byte = env->buffer->data + begin; end > byte; ++byte) { + if (*byte == env->magic) { + return byte - env->buffer->data; + } + } + + return env->buffer->end; +} + +bool XfcTransPackDecoderIsStartsWithMagick(tXfcProtDecoder *env) { + return env->buffer->data[0] == env->magic; +} + +bool XfcTransPackDecoderHasHeader(tXfcProtDecoder *env) { + return XfcArrayGetDataSize(env->buffer) >= XFC_TRANSPORT_HEADER_LEN; +} + +uint16_t XfcTransPackDecoderGetId(tXfcProtDecoder *env) { + return *((env->buffer->data + XFC_TRANSPORT_COMMAND_ID_OFFSET )); +} + +uint16_t XfcTransPackDecoderGetDataSegmentLength(tXfcProtDecoder *env) { + return *((uint16_t *) (env->buffer->data + XFC_TRANSPORT_DATA_LEN_OFFSET)); +} + + +uint16_t XfcTransPackDecoderGetCrc(tXfcProtDecoder *env) { + return *((uint16_t *) (env->buffer->data + XFC_TRANSPORT_HEADER_LEN + XfcTransPackDecoderGetDataSegmentLength(env))); +} + + +uint16_t XfcTransPackDecoderGetRequiredFullPackLength(tXfcProtDecoder *env) { + return XfcTransPackDecoderGetDataSegmentLength(env) + XFC_TRANSPORT_HEADER_LEN + XFC_TRANSPORT_CRC_LEN; +} + +bool XfcTransPackDecoderHasRequiredLength(tXfcProtDecoder *env) { + return XfcTransPackDecoderGetRequiredFullPackLength(env) <= XfcArrayGetDataSize(env->buffer); +} + +bool XfcTransPackDecoderIsCrcCorrect(tXfcProtDecoder *env) { + + return XfcProtCrc(env->buffer->data, XfcTransPackDecoderGetDataSegmentLength(env) + XFC_TRANSPORT_HEADER_LEN) == + XfcTransPackDecoderGetCrc(env); +} + +tXfcArray XfcTransPackDecoderGetDataSegmentAsArray(tXfcProtDecoder *env) { + uint16_t dataLen = XfcTransPackDecoderGetDataSegmentLength(env); + return (tXfcArray) { + .data = env->buffer->data + XFC_TRANSPORT_HEADER_LEN, + .begin = 0, + .end = dataLen, + .limit = dataLen, + }; +} diff --git a/Src/XfcProtEncoder.c b/Src/XfcProtEncoder.c new file mode 100644 index 0000000..272cd2d --- /dev/null +++ b/Src/XfcProtEncoder.c @@ -0,0 +1,41 @@ +// +// Created by xemon on 05.05.2022. +// + +#include "XfcProtEncoder.h" +#include "XfcProtCrc.h" +#include "XfcProtCommon.h" + + +////private +uint16_t XfcTransPackEncoderGetDataSegmentLength(tXfcProtEncoder *env) { + return *((uint16_t *) (env->buffer->data + XFC_TRANSPORT_DATA_LEN_OFFSET)); +} + +////public +tXfcArray XfcTransPackEncoderGetDataSegmentAsArray(tXfcProtEncoder *env) { + return (tXfcArray) { + .data = env->buffer->data + XFC_TRANSPORT_HEADER_LEN, + .begin = 0, + .end = 0, + .limit = env->buffer->limit - XFC_TRANSPORT_HEADER_LEN + XFC_TRANSPORT_CRC_LEN, + }; +} + + +void XfcTransPackEncoderSetId(tXfcProtEncoder *env, uint16_t id) { + *((env->buffer->data + XFC_TRANSPORT_COMMAND_ID_OFFSET)) = id; +} + +void XfcTransPackEncoderSetDataSegmentLength(tXfcProtEncoder *env, uint16_t dataSegmentLength) { + *((uint16_t *) (env->buffer->data + XFC_TRANSPORT_DATA_LEN_OFFSET)) = dataSegmentLength; +} + + +void XfcTransPackEncoderFinalizeAndSignCrc(tXfcProtEncoder *env) { + env->buffer->data[0] = env->magic; + uint16_t dataLen = XfcTransPackEncoderGetDataSegmentLength(env); + uint16_t crc = XfcProtCrc(env->buffer->data, dataLen + XFC_TRANSPORT_HEADER_LEN); + *((uint16_t *) (env->buffer->data + XFC_TRANSPORT_HEADER_LEN + dataLen)) = crc; + env->buffer->end = env->buffer->begin + dataLen + XFC_TRANSPORT_HEADER_LEN + XFC_TRANSPORT_CRC_LEN; +} \ No newline at end of file diff --git a/Src/XfcProtListener.c b/Src/XfcProtListener.c new file mode 100644 index 0000000..4617ce9 --- /dev/null +++ b/Src/XfcProtListener.c @@ -0,0 +1,133 @@ +// +// Created by xemon on 05.05.2022. +// + +#include +#include +#include "XfcProtListener.h" + + +void XfcProtListener_Reset(tXfcProtListener *env) { + XfcArrayClear(&env->requestBuffer); +} + +void XfcProtListener_Init( + tXfcProtListener *env, + + void *commonArgs, + tXfcProtTable *processors, + + tXfcArray requestBuffer, + uint8_t requestMagic +) { + env->commonArgs = commonArgs; + env->processors = processors; + + env->requestBuffer = requestBuffer; + env->requestDecoder.magic = requestMagic; + env->requestDecoder.buffer = &env->requestBuffer; + + XfcProtListener_Reset(env); +} + + +void XfcTransPackServiceListenerAddByte(tXfcProtListener *env, uint8_t byte) { + if (XfcArrayAddByte(&env->requestBuffer, byte)) { + ENV_COUNTER_INC(rx) + } else { + ENV_COUNTER_INC(rx_skip) + } +} + +void XfcProtListener_AddBytes(tXfcProtListener *env, uint8_t *bytes, uint16_t size) { + for (uint8_t *end = bytes + size; end > bytes; ++bytes) { + XfcTransPackServiceListenerAddByte(env, *bytes); + } +} + +void XfcProtListener_SkipToNextMagic(tXfcProtListener *env, uint16_t begin) { + + uint16_t skip = XfcTransPackDecoderNextMagicFrom(&env->requestDecoder, begin); + + XfcArrayRemoveBytesFront(&env->requestBuffer, skip); + +// ENV_COUNTER_ADD(rx_skip, nextMagic) +} + +bool XfcProtListener_isValidHeader(tXfcProtListener *env) { + return XfcArrayGetDataSize(&env->requestBuffer) && + XfcTransPackDecoderIsStartsWithMagick(&env->requestDecoder) && + XfcTransPackDecoderHasHeader(&env->requestDecoder); +} + +bool XfcProtListener_HasPacket(tXfcProtListener *env) { + + + while (XfcArrayGetDataSize(&env->requestBuffer)) { + + if (!XfcTransPackDecoderIsStartsWithMagick(&env->requestDecoder)) { + XfcProtListener_SkipToNextMagic(env, 1); + continue; + } + + + if (!XfcTransPackDecoderHasHeader(&env->requestDecoder)) { + return false; + } + + if (XfcTransPackDecoderGetRequiredFullPackLength(&env->requestDecoder) > + env->requestBuffer.limit) { + + ////Packet size bigger than buffer + XfcProtListener_SkipToNextMagic(env, 1); + continue; + + } + + if (!XfcTransPackDecoderHasRequiredLength(&env->requestDecoder)) { + return false; + } + + if (XfcTransPackDecoderIsCrcCorrect(&env->requestDecoder)) { + return true; + } else { + XfcProtListener_SkipToNextMagic(env, 1); + continue; + } + + } + + return false; +} + + +void XfcTransPackServiceListenerProcessRequest(tXfcProtListener *env) { + + uint8_t packId = XfcTransPackDecoderGetId(&env->requestDecoder); + + tXfcArray requestData = XfcTransPackDecoderGetDataSegmentAsArray(&env->requestDecoder); + + tXfcProtProcessor *proc = XfcProtTable_GetForId(env->processors, packId); + if (proc) { + + void *args = proc->args ? proc->args : env->commonArgs; + proc->process(&requestData, NULL, args); + + } +} + +void XfcProtListener_SkipCurrentRequest(tXfcProtListener *env) { + XfcProtListener_SkipToNextMagic(env, XfcTransPackDecoderGetRequiredFullPackLength(&env->requestDecoder)); +} + +bool XfcProtListener_Step(tXfcProtListener *env) { + + + if (XfcProtListener_HasPacket(env)) { + XfcTransPackServiceListenerProcessRequest(env); + return true; + } + + return false; +} + diff --git a/Src/XfcProtRequester.c b/Src/XfcProtRequester.c new file mode 100644 index 0000000..a05cca8 --- /dev/null +++ b/Src/XfcProtRequester.c @@ -0,0 +1,148 @@ +// +// Created by xemon on 07.11.23. +// + +#include +#include "XfcProtRequester.h" +#include "SerialPort.h" + +#define XFC_PROT_REQUESTER_DEFAULT_TIMEOUT (1000); + +void XfcProtRequester_reset(tXfcProtRequester *env) { + XfcArrayClear(&env->requestBuffer); + XfcArrayClear(&env->responseBuffer); +} + +void XfcProtRequester_init( + tXfcProtRequester *env, + + tSerialPortIO *io, + + tXfcArray requestBuffer, + tXfcArray responseBuffer, + + tXfcProtMagicNumbers magicNumbers +) { + + env->io = io; + + env->transmitTimeout = XFC_PROT_REQUESTER_DEFAULT_TIMEOUT; + + env->requestBuffer = requestBuffer; + env->responseBuffer = responseBuffer; + + env->encoder.magic = magicNumbers.request; + env->decoder.magic = magicNumbers.response; + + env->encoder.buffer = &env->requestBuffer; + env->decoder.buffer = &env->responseBuffer; + + XfcProtRequester_reset(env); +} + +eXfcProtRequesterStatus XfcProtRequester_makeRequest( + tXfcProtRequester *env, uint16_t id, + void *builder, tXfcRequesterMethod buildMethod, + void *parser, tXfcRequesterMethod parseMethod, + int32_t timeout +) { + + SerialPortClearRxBuffer(env->io); + XfcArrayClear(env->decoder.buffer); + XfcArrayClear(env->encoder.buffer); + + + tXfcArray request = XfcTransPackEncoderGetDataSegmentAsArray(&env->encoder); + XfcArrayClear(&request); + + if (buildMethod) { + switch (buildMethod(builder, &request)) { + + case XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_OK: + break; + case XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_CMD_OVERFLOW: + return eXfcProtRequesterStatus_REQUEST_BUILD_OVERFLOW; + + case XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_EXECUTION_ERROR: + return eXfcProtRequesterStatus_BUILD_EXECUTION_ERROR; + + default: + return eXfcProtRequesterStatus_UNKNOWN_ERROR; + } + } + + XfcTransPackEncoderSetId(&env->encoder, id); + XfcTransPackEncoderSetDataSegmentLength(&env->encoder, XfcArrayGetDataSize(&request)); + XfcTransPackEncoderFinalizeAndSignCrc(&env->encoder); + + uint16_t transmitted = SerialPortTransmit( + env->io, + env->encoder.buffer->data, + XfcArrayGetDataSize(env->encoder.buffer), + env->transmitTimeout + ); + + if (transmitted != XfcArrayGetDataSize(env->encoder.buffer)) { + return eXfcProtRequesterStatus_TRANSMIT_ERROR; + } + + uint8_t byte; + + int32_t timeEnd = SystemGetMs() + timeout; + + while (timeEnd >= SystemGetMs()) { + + if (!SerialPortReceive(env->io, &byte, 1, timeout)) { + continue; + } + + if (!XfcArrayAddByte(env->decoder.buffer, byte)) { + return eXfcProtRequesterStatus_RECIVE_BUFFER_OVERFLOW; + } + + if (!XfcTransPackDecoderIsStartsWithMagick(&env->decoder)) { + return eXfcProtRequesterStatus_PREFIX_MISMATCH; + } + + if (!XfcTransPackDecoderHasHeader(&env->decoder)) { + continue; + } + + if (XfcTransPackDecoderGetRequiredFullPackLength(&env->decoder) > env->decoder.buffer->limit) { + return eXfcProtRequesterStatus_RECIVE_BUFFER_OVERFLOW; + } + + if (!XfcTransPackDecoderHasRequiredLength(&env->decoder)) { + continue; + } + + if (!XfcTransPackDecoderIsCrcCorrect(&env->decoder)) { + return eXfcProtRequesterStatus_CRC_ERROR; + } + + tXfcArray response = XfcTransPackDecoderGetDataSegmentAsArray(&env->decoder); + + if (parseMethod) { + + switch (parseMethod(parser, &response)) { + case XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_OK: + break; + + case XFC_TRANSPORT_PROTOCOL_REQUEST_UNEXPECTEDLY_SHORT: + return eXfcProtRequesterStatus_RESPONSE_SHORT; + + case XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_EXECUTION_ERROR: + return eXfcProtRequesterStatus_PARSING_EXECUTION_ERROR; + + default: + return eXfcProtRequesterStatus_UNKNOWN_ERROR; + } + + } + + return eXfcProtRequesterStatus_OK; + } + + return eXfcProtRequesterStatus_RECIVE_TIMEOUT; + +} diff --git a/Src/XfcProtRespondent.c b/Src/XfcProtRespondent.c new file mode 100644 index 0000000..f4947a2 --- /dev/null +++ b/Src/XfcProtRespondent.c @@ -0,0 +1,150 @@ +// +// Created by xemon on 05.05.2022. +// + +#include +#include "XfcProtRespondent.h" + + +void XfcProcRespondent_Reset(tXfcProtRespondent *env) { + XfcArrayClear(&env->requestBuffer); + XfcArrayClear(&env->responseBuffer); +} + +void XfcProtRespondent_Init( + tXfcProtRespondent *env, + + void *commonArgs, + tXfcProtTable *processors, + + tXfcArray requestBuffer, + tXfcArray responseBuffer, + + tXfcProtMagicNumbers magicNumbers +) { + env->commonArgs = commonArgs; + env->processors = processors; + + env->requestBuffer = requestBuffer; + env->responseBuffer = responseBuffer; + + env->requestDecoder.magic = magicNumbers.request; + env->responseEncoder.magic = magicNumbers.response; + + env->requestDecoder.buffer = &env->requestBuffer; + env->responseEncoder.buffer = &env->responseBuffer; + + + XfcProcRespondent_Reset(env); +} + + +void XfcTransPackServiceRespondentAddByte(tXfcProtRespondent *env, uint8_t byte) { + if (XfcArrayAddByte(&env->requestBuffer, byte)) { + ENV_COUNTER_INC(rx) + } else { + ENV_COUNTER_INC(rx_skip) + } +} + +void +XfcProtRespondent_AddBytes(tXfcProtRespondent *env, uint8_t *bytes, uint16_t size) { + for (uint8_t *end = bytes + size; end > bytes; ++bytes) { + XfcTransPackServiceRespondentAddByte(env, *bytes); + } +} + +void XfcTransPackServiceRespondentSkipToNextMagic(tXfcProtRespondent *env, uint16_t begin) { + + uint16_t skip = XfcTransPackDecoderNextMagicFrom(&env->requestDecoder, begin); + + XfcArrayRemoveBytesFront(&env->requestBuffer, skip); + +// ENV_COUNTER_ADD(rx_skip, nextMagic) +} + +bool XfcTransPackServiceRespondentHasPacket(tXfcProtRespondent *env) { + + + while (XfcArrayGetDataSize(&env->requestBuffer)) { + + if (!XfcTransPackDecoderIsStartsWithMagick(&env->requestDecoder)) { + XfcTransPackServiceRespondentSkipToNextMagic(env, 1); + continue; + } + + if (!XfcTransPackDecoderHasHeader(&env->requestDecoder)) { + return false; + } + + if (XfcTransPackDecoderGetRequiredFullPackLength(&env->requestDecoder) > + env->requestBuffer.limit) { + + ////Packet size bigger than buffer + XfcTransPackServiceRespondentSkipToNextMagic(env, 1); + continue; + + } + + if (!XfcTransPackDecoderHasRequiredLength(&env->requestDecoder)) { + return false; + } + + if (XfcTransPackDecoderIsCrcCorrect(&env->requestDecoder)) { + return true; + } else { + XfcTransPackServiceRespondentSkipToNextMagic(env, 1); + continue; + } + + } + + return false; +} + + +void XfcTransPackServiceRespondentProcessRequest(tXfcProtRespondent *env) { + + uint8_t packId = XfcTransPackDecoderGetId(&env->requestDecoder); + + tXfcArray requestData = XfcTransPackDecoderGetDataSegmentAsArray(&env->requestDecoder); + tXfcArray responseData = XfcTransPackEncoderGetDataSegmentAsArray(&env->responseEncoder); + + XfcArrayClear(&responseData); + + tXfcTransportProtocolResponseCode responseCode; + tXfcProtProcessor *proc = XfcProtTable_GetForId(env->processors, packId); + + if (proc) { + void *args = proc->args ? proc->args : env->commonArgs; + responseCode = proc->process(&requestData, &responseData, args); + + if (responseCode != XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_OK) { + XfcArrayClear(&responseData); + } + } else { + responseCode = XFC_TRANSPORT_PROTOCOL_RESPONSE_RESULT_CMD_UNKNOWN; + } + + XfcTransPackEncoderSetId(&env->responseEncoder, responseCode); + XfcTransPackEncoderSetDataSegmentLength(&env->responseEncoder, XfcArrayGetDataSize(&responseData)); + XfcTransPackEncoderFinalizeAndSignCrc(&env->responseEncoder); + +} + +void XfcProtRespondent_SkipCurrentRequest(tXfcProtRespondent *env) { + XfcTransPackServiceRespondentSkipToNextMagic(env, + XfcTransPackDecoderGetRequiredFullPackLength(&env->requestDecoder)); +} + +bool XfcProtRespondent_Step(tXfcProtRespondent *env) { + + + if (XfcTransPackServiceRespondentHasPacket(env)) { + XfcTransPackServiceRespondentProcessRequest(env); + return true; + } + + return false; +} + diff --git a/Src/XfcProtTable.c b/Src/XfcProtTable.c new file mode 100644 index 0000000..d6dd519 --- /dev/null +++ b/Src/XfcProtTable.c @@ -0,0 +1,47 @@ +// +// Created by xemon on 01.11.22. +// + +#include +#include +#include "XfcProtTable.h" + +void XfcProtTable_Init(tXfcProtTable *env, tXfcProtProcessor *allocatedMem, uint16_t memLimit) { + env->limit = memLimit; + env->items = allocatedMem; + env->count = 0; + memset(env->items, 0, env->limit * sizeof(tXfcProtProcessor)); +} + +bool XfcProtTable_Add( + tXfcProtTable *env, + char *staticStringTextId, + uint8_t textIdLen, + tXfcProtMethod method, + void *args +) { + if (env->limit <= env->count) { + return false; + } + tXfcProtProcessor *proc = env->items + env->count; + + proc->textId = staticStringTextId; + proc->textIdLen = textIdLen; + proc->args = args; + proc->process = method; + + ++env->count; + + return true; +} + + +tXfcProtProcessor *XfcProtTable_GetForId(tXfcProtTable *env, uint16_t id) { + if ((id < env->count) && env->items[id].process) { + return &env->items[id]; + } else { + return NULL; + } +} + + diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..71971cd --- /dev/null +++ b/modular.json @@ -0,0 +1,10 @@ +{ + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file