From 0d399967fdb52f70befc8ef7912d069d916a355c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 22 Mar 2016 22:10:59 +0100 Subject: [PATCH] updated sbmp to the esp branch --- .gitmodules | 4 + esp_meas.pro | 28 +-- sbmp | 1 + sbmp-/README.md | 110 ----------- sbmp-/crc32.c | 144 -------------- sbmp-/crc32.h | 51 ----- sbmp-/sbmp.h | 25 --- sbmp-/sbmp_checksum.c | 105 ---------- sbmp-/sbmp_checksum.h | 39 ---- sbmp-/sbmp_config.h | 53 ----- sbmp-/sbmp_datagram.c | 69 ------- sbmp-/sbmp_datagram.h | 71 ------- sbmp-/sbmp_frame.c | 442 ------------------------------------------ sbmp-/sbmp_frame.h | 205 -------------------- sbmp-/sbmp_logging.h | 15 -- sbmp-/sbmp_session.c | 416 --------------------------------------- sbmp-/sbmp_session.h | 207 -------------------- 17 files changed, 20 insertions(+), 1965 deletions(-) create mode 100644 .gitmodules create mode 160000 sbmp delete mode 100644 sbmp-/README.md delete mode 100644 sbmp-/crc32.c delete mode 100644 sbmp-/crc32.h delete mode 100644 sbmp-/sbmp.h delete mode 100644 sbmp-/sbmp_checksum.c delete mode 100644 sbmp-/sbmp_checksum.h delete mode 100644 sbmp-/sbmp_config.h delete mode 100644 sbmp-/sbmp_datagram.c delete mode 100644 sbmp-/sbmp_datagram.h delete mode 100644 sbmp-/sbmp_frame.c delete mode 100644 sbmp-/sbmp_frame.h delete mode 100644 sbmp-/sbmp_logging.h delete mode 100644 sbmp-/sbmp_session.c delete mode 100644 sbmp-/sbmp_session.h diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..370c224 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "sbmp"] + path = sbmp + url = git@github.com:MightyPork/sbmp.git + branch = esp8266 diff --git a/esp_meas.pro b/esp_meas.pro index e5e67d8..d6f6c64 100644 --- a/esp_meas.pro +++ b/esp_meas.pro @@ -43,11 +43,12 @@ SOURCES += \ user/io.c \ user/user_main.c \ user/uart_driver.c \ - sbmp/crc32.c \ - sbmp/sbmp_checksum.c \ - sbmp/sbmp_datagram.c \ - sbmp/sbmp_frame.c \ - sbmp/sbmp_session.c \ + sbmp/library/crc32.c \ + sbmp/library/sbmp_checksum.c \ + sbmp/library/sbmp_datagram.c \ + sbmp/library/sbmp_frame.c \ + sbmp/library/sbmp_session.c \ + sbmp/library/sbmp_bulk.c \ user/datalink.c \ user/serial.c \ user/uptime.c @@ -111,14 +112,15 @@ HEADERS += \ esp_iot_sdk_v1.5.2/include/upgrade.h \ esp_iot_sdk_v1.5.2/include/user_interface.h \ user/uart_driver.h \ - sbmp/crc32.h \ - sbmp/sbmp.h \ - sbmp/sbmp_checksum.h \ - sbmp/sbmp_config.h \ - sbmp/sbmp_datagram.h \ - sbmp/sbmp_frame.h \ - sbmp/sbmp_logging.h \ - sbmp/sbmp_session.h \ + sbmp/library/crc32.h \ + sbmp/library/sbmp.h \ + sbmp/library/sbmp_checksum.h \ + sbmp/library/sbmp_config.h \ + sbmp/library/sbmp_datagram.h \ + sbmp/library/sbmp_frame.h \ + sbmp/library/sbmp_logging.h \ + sbmp/library/sbmp_session.h \ + sbmp/library/sbmp_bulk.h \ user/datalink.h \ user/serial.h \ libesphttpd/include/logging.h \ diff --git a/sbmp b/sbmp new file mode 160000 index 0000000..5548d82 --- /dev/null +++ b/sbmp @@ -0,0 +1 @@ +Subproject commit 5548d820959ddba33ffb7d2ff76a3ee8d95e1be6 diff --git a/sbmp-/README.md b/sbmp-/README.md deleted file mode 100644 index b1ed69b..0000000 --- a/sbmp-/README.md +++ /dev/null @@ -1,110 +0,0 @@ -SBMP library, v1.3 -================== - -This is a reference implementation of SBMP, which should be usable in embedded -environment. - -The library cosists of a **Framing layer**, **Datagram middleware** and a **Session layer**. - -How to use ----------- - -The framing layer is isolated in the `sbmp_frame` module, and can be used on it's own, -if sessions are not needed. That gives you reliable data transfer with error detection. - -If you want to *get the most out of SBMP*, use the session layer. Session layer functions are -namespaced `sbmp_ep_` ("ep" stands for endpoint). - -All header files are included in `sbmp.h`, which is the only file you should -`#include` in your application. - -Read comments in the examples to see how to use the library. - -Configuration & porting ------------------------ - -You can customize a lot of aspects of SBMP in `sbmp_config.h`. - -If you included the library as a submodule, and want to avoid manual edits, you can set -the options using compiler flags (eg. to disable CRC32: `-DSBMP_HAS_CRC32=0`). - -**What to change for Arduino** - -Basically disable all you can in the config file. - -- You don't want `malloc()` -- Logging is useless if there's only one USART anyway -- CRC32 can be replaced with XOR if you don't care about reliability that much. - -This gains you a huge size reduction, and the whole library will take only around -2.5 kB flash and 150 B ram (of course, not including your Rx buffer). - -It works really well for ATmega328P - the usual Arduino chip. - -Example for AVR ---------------- - -This example uses the [AVR C boilerplate](https://github.com/MightyPork/avr-c-boilerplate). - -It's here just to show how to set up SBMP in your AVR application. - -**NOTE:** This example uses static allocation of the struct and buffer. - -If you pass NULLs to the init function, it will `malloc()` it for you -and return a pointer to the Endpoint. - -```c -#include // register definitions -#include // interrupt vectors - -#include -#include - -// AVR C boilerplate libs -#include "lib/iopins.h" -#include "lib/usart.h" - -// SBMP -#include "sbmp/sbmp.h" - -// SBMP globals -#define RXBUF_LEN 128 -static uint8_t rxbuf[RXBUF_LEN]; -static SBMP_Endpoint ep; - -/** USART receive handler */ -ISR(USART_RX_vect) -{ - // Get the byte and pass it to SBMP - uint8_t b = usart_rx(); - sbmp_ep_receive(&ep, b); // WARN: This can fail. Should check retval. -} - -/** Message received from SBMP */ -void message_received(SBMP_Datagram *dg) -{ - // ... -} - -int main() -{ - usart_init(BAUD_115200); - usart_isr_rx_enable(true); // enable the interrupt - - // init SBMP - sbmp_ep_init(&ep, rxbuf, RXBUF_LEN, message_received, usart_tx); - - // ...additional SBMP configuration if needed... - - // enable rx, tx - sbmp_ep_enable(&ep, true); - - // globally enable interrupts (for the USART_RX handler) - sei(); - - while (1) { - // ... do stuff - } -} -``` - diff --git a/sbmp-/crc32.c b/sbmp-/crc32.c deleted file mode 100644 index e461f12..0000000 --- a/sbmp-/crc32.c +++ /dev/null @@ -1,144 +0,0 @@ -#include "esp8266.h" - -#include "crc32.h" -#include "sbmp_config.h" - -#if SBMP_HAS_CRC32 - -// This file was downloaded from some forum, and modified a bit. - -/**********************************************************************\ -|* Demonstration program to compute the 32-bit CRC used as the frame *| -|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| -|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| -|* protocol). The 32-bit FCS was added via the Federal Register, *| -|* 1 June 1982, p.23798. I presume but don't know for certain that *| -|* this polynomial is or will be included in CCITT V.41, which *| -|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| -|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| -|* errors by a factor of 10^-5 over 16-bit FCS. *| -\**********************************************************************/ - - -/* Copyright (C) 1986 Gary S. Brown. You may use this program, or - code or tables extracted from it, as desired without restriction.*/ - -/* First, the polynomial itself and its table of feedback terms. The */ -/* polynomial is */ -/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ -/* Note that we take it "backwards" and put the highest-order term in */ -/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ -/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ -/* the MSB being 1. */ - -/* Note that the usual hardware shift register implementation, which */ -/* is what we're using (we're merely optimizing it by doing eight-bit */ -/* chunks at a time) shifts bits into the lowest-order term. In our */ -/* implementation, that means shifting towards the right. Why do we */ -/* do it this way? Because the calculated CRC must be transmitted in */ -/* order from highest-order term to lowest-order term. UARTs transmit */ -/* characters in order from LSB to MSB. By storing the CRC this way, */ -/* we hand it to the UART in the order low-byte to high-byte; the UART */ -/* sends each low-bit to hight-bit; and the result is transmission bit */ -/* by bit from highest- to lowest-order term without requiring any bit */ -/* shuffling on our part. Reception works similarly. */ - -/* The feedback terms table consists of 256, 32-bit entries. Notes: */ -/* */ -/* 1. The table can be generated at runtime if desired; code to do so */ -/* is shown later. It might not be obvious, but the feedback */ -/* terms simply represent the results of eight shift/xor opera- */ -/* tions for all combinations of data and CRC register values. */ -/* */ -/* 2. The CRC accumulation logic is the same for all CRC polynomials, */ -/* be they sixteen or thirty-two bits wide. You simply choose the */ -/* appropriate table. Alternatively, because the table can be */ -/* generated at runtime, you can start by generating the table for */ -/* the polynomial in question and use exactly the same "updcrc", */ -/* if your application needn't simultaneously handle two CRC */ -/* polynomials. (Note, however, that XMODEM is strange.) */ -/* */ -/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ -/* of course, 32-bit entries work OK if the high 16 bits are zero. */ -/* */ -/* 4. The values must be right-shifted by eight bits by the "updcrc" */ -/* logic; the shift must be unsigned (bring in zeroes). On some */ -/* hardware you could probably optimize the shift in assembler by */ -/* using byte-swap instructions. */ - -static uint32_t FLASH_DATA crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - - -#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ ((uint8_t)octet)) & 0xff] ^ ((crc) >> 8)) - -uint32_t FLASH_FN crc32_begin(void) -{ - return 0xFFFFFFFF; -} - -uint32_t FLASH_FN crc32_update(uint32_t crc_scratch, uint8_t ch) -{ - return UPDC32(ch, crc_scratch); -} - -uint32_t FLASH_FN crc32_end(uint32_t crc_scratch) -{ - return ~crc_scratch; -} - -uint32_t FLASH_FN crc32buf(uint8_t *buf, size_t len) -{ - uint32_t scratch = crc32_begin(); - - for (; len; --len, ++buf) { - scratch = crc32_update(scratch, *buf); - } - - return crc32_end(scratch); -} - -#endif /* SBMP_HAS_CRC32 */ diff --git a/sbmp-/crc32.h b/sbmp-/crc32.h deleted file mode 100644 index 383900e..0000000 --- a/sbmp-/crc32.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef CRC32_H -#define CRC32_H - -#include "sbmp_config.h" -#if SBMP_HAS_CRC32 - -/** - * This module is used by the framing layer to calculate CRC32. - * - * If your hardware provides a hardware checksum calculator, - * you can modify the .c file to use that instead of - * doing it in software. - */ - -#include -#include -#include - -/** - * @brief Calculate CRC32 of a buffer. - * @param buf : buffer to checksum - * @param len : buffer size - * @return the CRC32 checksum - */ -uint32_t crc32buf(uint8_t *buf, size_t len); - -/** - * @brief Start calculating a checksum of a block of data. - * @return the scratch value, for use in the update and end functions. - */ -uint32_t crc32_begin(void); - -/** - * @brief Update the CRC32 scratch value with a byte of the data block. - * @param crc_scratch : old scratch value pointer. - * @param b : received byte - * @return updated scratch - */ -uint32_t crc32_update(uint32_t crc_scratch, uint8_t b); - -/** - * @brief Finish the CRC calculation. - * @param crc_scratch : your scratch buffer. - * @return the final CRC32 value. - */ -uint32_t crc32_end(uint32_t crc_scratch); - - -#endif /* SBMP_HAS_CRC32 */ - -#endif /* CRC32_H */ diff --git a/sbmp-/sbmp.h b/sbmp-/sbmp.h deleted file mode 100644 index dd2de61..0000000 --- a/sbmp-/sbmp.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SBMP_H -#define SBMP_H - -/** - * This is the main SBMP header file. - * - * This is the only header file you should need to - * #include in your application code. - */ - -#define SBMP_VER "1.3" - -#include "sbmp_config.h" - -// Common utils & the frame parser -#include "sbmp_logging.h" -#include "sbmp_checksum.h" - -#include "sbmp_frame.h" - -// Datagram & session layer -#include "sbmp_datagram.h" -#include "sbmp_session.h" - -#endif /* SBMP_H */ diff --git a/sbmp-/sbmp_checksum.c b/sbmp-/sbmp_checksum.c deleted file mode 100644 index 8ceb4ee..0000000 --- a/sbmp-/sbmp_checksum.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "esp8266.h" - -#include - -#include "sbmp_config.h" -#include "sbmp_checksum.h" - -#if SBMP_HAS_CRC32 -#include "crc32.h" -#endif - - -/** Get nr of bytes in a checksum */ -uint8_t FLASH_FN chksum_length(SBMP_CksumType cksum_type) -{ - switch (cksum_type) { - case SBMP_CKSUM_CRC32: return 4; - case SBMP_CKSUM_XOR: return 1; - case SBMP_CKSUM_NONE: return 0; - default: - return 4; // assume all unknown checksums are 4 bytes long - } -} - -/** Start calculating a checksum */ -void FLASH_FN cksum_begin(SBMP_CksumType type, uint32_t *scratch) -{ - switch (type) { - -#if SBMP_HAS_CRC32 - case SBMP_CKSUM_CRC32: - *scratch = crc32_begin(); - break; -#endif - case SBMP_CKSUM_XOR: - *scratch = 0; - break; - - case SBMP_CKSUM_NONE: // fall-through - default: - ; - } -} - -/** Update the checksum calculation with an incoming byte */ -void FLASH_FN cksum_update(SBMP_CksumType type, uint32_t *scratch, uint8_t byte) -{ - switch (type) { - -#if SBMP_HAS_CRC32 - case SBMP_CKSUM_CRC32: - *scratch = crc32_update(*scratch, byte); - break; -#endif - case SBMP_CKSUM_XOR: - *scratch ^= byte; - break; - - case SBMP_CKSUM_NONE: // fall-through - default: - ; - } -} - -/** Stop the checksum calculation, get the result */ -void FLASH_FN cksum_end(SBMP_CksumType type, uint32_t *scratch) -{ - switch (type) { - -#if SBMP_HAS_CRC32 - case SBMP_CKSUM_CRC32: - *scratch = crc32_end(*scratch); -#endif - case SBMP_CKSUM_XOR: - // scratch already contains the checksum - break; - - case SBMP_CKSUM_NONE: // fall-through - default: - *scratch = 0; - break; - } -} - -/** Check if the calculated checksum matches the received one */ -bool FLASH_FN cksum_verify(SBMP_CksumType type, uint32_t *scratch, uint32_t received_cksum) -{ - cksum_end(type, scratch); - - // scratch now contains the checksum - - switch (type) { - -#if SBMP_HAS_CRC32 - case SBMP_CKSUM_CRC32: // fall-through -#endif - case SBMP_CKSUM_XOR: - return (*scratch == received_cksum); - - case SBMP_CKSUM_NONE: // fall-through - default: - // unknown checksum type - return true; // assume it's OK - } -} diff --git a/sbmp-/sbmp_checksum.h b/sbmp-/sbmp_checksum.h deleted file mode 100644 index 6435608..0000000 --- a/sbmp-/sbmp_checksum.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef SBMP_CHECKSUM_H -#define SBMP_CHECKSUM_H - -/** - * Checksum functions for the SBMP framing layer. - */ - -#include -#include - -#include "sbmp_config.h" - - -/** Checksum types */ -typedef enum { - SBMP_CKSUM_NONE = 0, /*!< No checksum */ - SBMP_CKSUM_CRC32 = 32, /*!< ISO CRC-32 */ - SBMP_CKSUM_XOR = 1, /*!< Simple XOR check, good for small micros (Arduino) */ - -} SBMP_CksumType; - - -/** Get nr of bytes in a checksum */ -uint8_t chksum_length(SBMP_CksumType cksum_type); - -/** Start calculating a checksum. Updates scratch. */ -void cksum_begin(SBMP_CksumType type, uint32_t *scratch); - -/** Update the checksum calculation with an incoming byte. Updates scratch. */ -void cksum_update(SBMP_CksumType type, uint32_t *scratch, uint8_t byte); - -/** Stop the checksum calculation, get the result */ -void cksum_end(SBMP_CksumType type, uint32_t *scratch); - -/** Check if the calculated checksum matches the received one */ -bool cksum_verify(SBMP_CksumType type, uint32_t *scratch, uint32_t received_cksum); - - -#endif /* SBMP_CHECKSUM_H */ diff --git a/sbmp-/sbmp_config.h b/sbmp-/sbmp_config.h deleted file mode 100644 index 01dbc74..0000000 --- a/sbmp-/sbmp_config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef SBMP_CONFIG_H -#define SBMP_CONFIG_H - -/* --- Configuration ------------------- */ - - -#ifndef SBMP_LOGGING -/** - * @brief Enable logging. - * - * Logging functions are WEAK stubs in sbmp_logging. - * - * Disable logging to free up memory taken by the messages. - */ -#define SBMP_LOGGING 1 -#endif - - -#ifndef SBMP_MALLOC -/** - * @brief Enable malloc if NULL is passed. - * - * This lets you malloc() the struct / buffer if you pass NULL - * to the init functions. - * - * Disable malloc to free up memory taken by the malloc routine. - * If disabled, init funcs will return NULL if NULL is passed - * as argument. - */ -#define SBMP_MALLOC 1 -#endif - - -#ifndef SBMP_HAS_CRC32 -/** - * @brief Add support for CRC32 - * - * Disabling CRC32 will reduce program size (for small micros). - * If CRC32 is disabled, XOR will be used as the preferred checksum - * method. - * - * Received CRC32'd messages will be accepted without checking. - * - * If handshake is used, the peer will detect that CRC32 is not - * supported here, and should start using XOR. - */ -#define SBMP_HAS_CRC32 1 -#endif - -/* ------------------------------------- */ - - -#endif // SBMP_CONFIG_H diff --git a/sbmp-/sbmp_datagram.c b/sbmp-/sbmp_datagram.c deleted file mode 100644 index 09a48e6..0000000 --- a/sbmp-/sbmp_datagram.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "esp8266.h" - -#include "sbmp_config.h" -#include "sbmp_logging.h" -#include "sbmp_datagram.h" - -SBMP_Datagram FLASH_FN *sbmp_dg_parse(SBMP_Datagram *dg, const uint8_t *payload, uint16_t length) -{ - if (length < 3) { - sbmp_error("Can't parse datagram, payload too short."); - return NULL; // shorter than the minimal no-payload datagram - } - - // S.N. (2 B) | Dg Type (1 B) | Payload - -#if SBMP_MALLOC - if (dg == NULL) { - // request to allocate - dg = malloc(sizeof(SBMP_Datagram)); - } -#else - if (dg == NULL) { - return NULL; // fail - } -#endif - - dg->session = (uint16_t)((payload[0]) | (payload[1] << 8)); - dg->type = payload[2]; - dg->length = length - 3; - dg->payload = payload + 3; // pointer arith - - return dg; -} - - -/** Start a datagram transmission */ -bool FLASH_FN sbmp_dg_start(SBMP_FrmInst *frm, SBMP_CksumType cksum_type, uint16_t session, SBMP_DgType type, uint16_t length) -{ - if (length > (0xFFFF - 3)) { - sbmp_error("Can't send a datagram, payload too long."); - return false; - } - - if (frm->tx_status != FRM_STATE_IDLE) { - sbmp_error("Can't state datagram, SBMP tx not IDLE."); - return false; - } - - if (! sbmp_frm_start(frm, cksum_type, length + 3)) return false; - - sbmp_frm_send_byte(frm, session & 0xFF); - sbmp_frm_send_byte(frm, (session >> 8) & 0xFF); - sbmp_frm_send_byte(frm, type); - - return true; -} - - -/** Send a whole datagram in one go */ -bool FLASH_FN sbmp_dg_send(SBMP_FrmInst *frm, SBMP_CksumType cksum_type, SBMP_Datagram *dg) -{ - if (! sbmp_dg_start(frm, cksum_type, dg->session, dg->type, dg->length)) { - sbmp_error("Failed to start datagram."); - return false; - } - - size_t n = sbmp_frm_send_buffer(frm, dg->payload, dg->length); - return (n == dg->length); -} diff --git a/sbmp-/sbmp_datagram.h b/sbmp-/sbmp_datagram.h deleted file mode 100644 index 65a64fd..0000000 --- a/sbmp-/sbmp_datagram.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef SBMP_DATAGRAM_H -#define SBMP_DATAGRAM_H - -/** - * SBMP datagram layer - * - * This layer is coupled to the framing layer, and - * builds a datagram abstraction on top of it. - * - * This layer sits right under the session layer, - * and is not very useful on it's own. - */ - -#include - -#include "sbmp_config.h" -#include "sbmp_frame.h" - -typedef uint8_t SBMP_DgType; -#define SBMP_DG_HSK_START 0x00 -#define SBMP_DG_HSK_ACCEPT 0x01 -#define SBMP_DG_HSK_CONFLICT 0x02 - -/** - * SBMP datagram object. - */ -typedef struct { - const uint8_t *payload; /*!< Datagram payload */ - SBMP_DgType type; /*!< Datagram type ID */ - uint16_t length; /*!< Datagram length (bytes) */ - uint16_t session; /*!< Datagram session number */ -} SBMP_Datagram; - - -/** - * @brief Convert a received buffer payload to a datagram. - * - * If the payload is < 3 bytes long, datagram can't be createdn and NULL - * is returned instead. The caller should then free the payload buffer. - * - * @param dg : datagram variable to populate, or NULL to allocate - * @param frame_payload : frame payload to parse - * @param length : frame payload length - * @return datagram (allocated if dg was NULL), or NULL if parsing failed. - */ -SBMP_Datagram *sbmp_dg_parse(SBMP_Datagram *dg_or_null, const uint8_t *frame_payload, uint16_t length); - -/** - * @brief Start a datagram (and the frame) - * - * @param state : SBMP state struct - * @param cksum_type : Checksum type to use for the frame; 0 - none, 32 - CRC32 - * @param session : session number - * @param type : Datagram type ID - * @param length : Datagram payload length (bytes) - * @return success - */ -bool sbmp_dg_start(SBMP_FrmInst *frm, SBMP_CksumType cksum_type, uint16_t session, SBMP_DgType type, uint16_t length); - -/** - * @brief Send a complete prepared datagram, also starts the frame. - * - * @param state : SBMP state struct - * @param cksum_type : Checksum type to use for the frame; 0 - none, 32 - CRC32 - * @param dg : Datagram struct containing DG settings and the payload. - * @return success - */ -bool sbmp_dg_send(SBMP_FrmInst *frm, SBMP_CksumType cksum_type, SBMP_Datagram *dg); - - -#endif /* SBMP_DATAGRAM_H */ diff --git a/sbmp-/sbmp_frame.c b/sbmp-/sbmp_frame.c deleted file mode 100644 index 79103a4..0000000 --- a/sbmp-/sbmp_frame.c +++ /dev/null @@ -1,442 +0,0 @@ -#include "esp8266.h" - -#include - -#include "sbmp_config.h" -#include "sbmp_logging.h" -#include "sbmp_checksum.h" -#include "sbmp_frame.h" - -// protos -static void call_frame_rx_callback(SBMP_FrmInst *frm); - - -/** Allocate the state struct & init all fields */ -SBMP_FrmInst FLASH_FN *sbmp_frm_init( - SBMP_FrmInst *frm, - uint8_t *buffer, - uint16_t buffer_size, - void (*rx_handler)(uint8_t *, uint16_t, void *), - void (*tx_func)(uint8_t)) -{ - -#if SBMP_MALLOC - - if (frm == NULL) { - // caller wants us to allocate it - frm = malloc(sizeof(SBMP_FrmInst)); - } - - if (buffer == NULL) { - // caller wants us to allocate it - buffer = malloc(buffer_size); - } - -#else - - if (frm == NULL || buffer == NULL) { - return NULL; // malloc not enabled, fail - } - -#endif - - frm->rx_handler = rx_handler; - - frm->rx_buffer = buffer; - frm->rx_buffer_cap = buffer_size; - - frm->user_token = NULL; // NULL if not set - - frm->tx_func = tx_func; - - frm->rx_enabled = false; - frm->tx_enabled = false; - - sbmp_frm_reset(frm); - - return frm; -} - -/** Reset the internal state */ -void FLASH_FN sbmp_frm_reset(SBMP_FrmInst *frm) -{ - sbmp_frm_reset_rx(frm); - sbmp_frm_reset_tx(frm); -} - -/** Enable or disable Rx */ -void FLASH_FN sbmp_frm_enable_rx(SBMP_FrmInst *frm, bool enable) -{ - frm->rx_enabled = enable; -} - -/** Enable or disable Tx */ -void FLASH_FN sbmp_frm_enable_tx(SBMP_FrmInst *frm, bool enable) -{ - frm->tx_enabled = enable; -} - -/** Enable or disable both Rx and Tx */ -void FLASH_FN sbmp_frm_enable(SBMP_FrmInst *frm, bool enable) -{ - sbmp_frm_enable_rx(frm, enable); - sbmp_frm_enable_tx(frm, enable); -} - -/** Set user token */ -void FLASH_FN sbmp_frm_set_user_token(SBMP_FrmInst *frm, void *token) -{ - frm->user_token = token; -} - -/** Reset the receiver state */ -void FLASH_FN sbmp_frm_reset_rx(SBMP_FrmInst *frm) -{ - frm->rx_buffer_i = 0; - frm->rx_length = 0; - frm->mb_buf = 0; - frm->mb_cnt = 0; - frm->rx_hdr_xor = 0; - frm->rx_cksum_scratch = 0; - frm->rx_cksum_type = SBMP_CKSUM_NONE; - frm->rx_status = FRM_STATE_IDLE; -// printf("---- RX RESET STATE ----\n"); -} - -/** Reset the transmitter state */ -void FLASH_FN sbmp_frm_reset_tx(SBMP_FrmInst *frm) -{ - frm->tx_status = FRM_STATE_IDLE; - frm->tx_remain = 0; - frm->tx_cksum_scratch = 0; - frm->tx_cksum_type = SBMP_CKSUM_NONE; -// printf("---- TX RESET STATE ----\n"); -} - -/** Update a header XOR */ -static inline FLASH_FN -void hdrxor_update(SBMP_FrmInst *frm, uint8_t rxbyte) -{ - frm->rx_hdr_xor ^= rxbyte; -} - -/** Check header xor against received value */ -static inline FLASH_FN -bool hdrxor_verify(SBMP_FrmInst *frm, uint8_t rx_xor) -{ - return frm->rx_hdr_xor == rx_xor; -} - -/** Append a byte to the rx buffer */ -static inline FLASH_FN -void append_rx_byte(SBMP_FrmInst *frm, uint8_t b) -{ - frm->rx_buffer[frm->rx_buffer_i++] = b; -} - -/** Set n-th byte (0 = LSM) to a value */ -static inline -void FLASH_FN set_byte(uint32_t *acc, uint8_t pos, uint8_t byte) -{ - *acc |= (uint32_t)(byte << (pos * 8)); -} - -/** - * Call the message handler with the payload. - * - */ -static void FLASH_FN call_frame_rx_callback(SBMP_FrmInst *frm) -{ - if (frm->rx_handler == NULL) { - sbmp_error("frame_handler is null!"); - return; - } - - frm->rx_status = FRM_STATE_WAIT_HANDLER; - frm->rx_handler(frm->rx_buffer, frm->rx_length, frm->user_token); -} - -/** - * @brief Receive a byte - * - * SOF 8 | CKSUM_TYPE 8 | LEN 16 | PAYLOAD | CKSUM 0/4 - * - * @param state - * @param rxbyte - * @return status - */ -SBMP_RxStatus FLASH_FN sbmp_frm_receive(SBMP_FrmInst *frm, uint8_t rxbyte) -{ - if (! frm->rx_enabled) { - return SBMP_RX_DISABLED; - } - - SBMP_RxStatus retval = SBMP_RX_OK; - - switch (frm->rx_status) { - case FRM_STATE_WAIT_HANDLER: - retval = SBMP_RX_BUSY; - break; - - case FRM_STATE_IDLE: - // can be first byte of a packet - - if (rxbyte == 0x01) { // start byte - - hdrxor_update(frm, rxbyte); - - frm->rx_status = FRM_STATE_CKSUM_TYPE; - } else { - // bad char - retval = SBMP_RX_INVALID; - } - break; - - case FRM_STATE_CKSUM_TYPE: - frm->rx_cksum_type = rxbyte; // checksum type received - - hdrxor_update(frm, rxbyte); - - // next will be length - frm->rx_status = FRM_STATE_LENGTH; - // clear MB for 2-byte length - frm->mb_buf = 0; - frm->mb_cnt = 0; - break; - - case FRM_STATE_LENGTH: - // append to the multi-byte buffer - set_byte(&frm->mb_buf, frm->mb_cnt++, rxbyte); - - hdrxor_update(frm, rxbyte); - - // if last of the MB field - if (frm->mb_cnt == 2) { - - // next will be the payload - uint16_t len = (uint16_t) frm->mb_buf; - frm->rx_length = len; - - if (len == 0) { - sbmp_error("Rx packet with no payload!"); - sbmp_frm_reset_rx(frm); // abort - break; - } - - frm->rx_status = FRM_STATE_HDRXOR; - } - break; - - case FRM_STATE_HDRXOR: - if (! hdrxor_verify(frm, rxbyte)) { - sbmp_error("Header XOR mismatch!"); - sbmp_frm_reset_rx(frm); // abort - break; - } - - // Check if not too long - if (frm->rx_length > frm->rx_buffer_cap) { - sbmp_error("Rx packet too long - %d!", (uint16_t)frm->rx_length); - // discard the rest + checksum - frm->rx_status = FRM_STATE_DISCARD; - frm->rx_length += chksum_length(frm->rx_cksum_type); - break; - } - - frm->rx_status = FRM_STATE_PAYLOAD; - cksum_begin(frm->rx_cksum_type, &frm->rx_cksum_scratch); - break; - - case FRM_STATE_DISCARD: - frm->rx_buffer_i++; - if (frm->rx_buffer_i == frm->rx_length) { - // done - sbmp_frm_reset_rx(frm); // go IDLE - } - break; - - case FRM_STATE_PAYLOAD: - append_rx_byte(frm, rxbyte); - cksum_update(frm->rx_cksum_type, &frm->rx_cksum_scratch, rxbyte); - - if (frm->rx_buffer_i == frm->rx_length) { - // payload rx complete - - if (frm->rx_cksum_type != SBMP_CKSUM_NONE) { - // receive the checksum - frm->rx_status = FRM_STATE_CKSUM; - - // clear MB for the 4-byte length - frm->mb_buf = 0; - frm->mb_cnt = 0; - } else { - // no checksum - // fire the callback - call_frame_rx_callback(frm); - - // clear - sbmp_frm_reset_rx(frm); - } - } - break; - - case FRM_STATE_CKSUM: - // append to the multi-byte buffer - set_byte(&frm->mb_buf, frm->mb_cnt++, rxbyte); - - // if last of the MB field - if (frm->mb_cnt == chksum_length(frm->rx_cksum_type)) { - - if (cksum_verify(frm->rx_cksum_type, &frm->rx_cksum_scratch, frm->mb_buf)) { - call_frame_rx_callback(frm); - } else { - sbmp_error("Rx checksum mismatch!"); - } - - // clear, enter IDLE - sbmp_frm_reset_rx(frm); - } - break; - } - - return retval; -} - -/** Send a frame header */ -bool FLASH_FN sbmp_frm_start(SBMP_FrmInst *frm, SBMP_CksumType cksum_type, uint16_t length) -{ - if (! frm->tx_enabled) { - sbmp_error("Can't tx, not enabled."); - return false; - } - - if (frm->tx_status != FRM_STATE_IDLE) { - sbmp_error("Can't tx, busy."); - return false; - } - - if (frm->tx_func == NULL) { - sbmp_error("Can't tx, no tx func!"); - return false; - } - - if (cksum_type == SBMP_CKSUM_CRC32 && !SBMP_HAS_CRC32) { - sbmp_error("CRC32 disabled, using XOR for Tx."); - cksum_type = SBMP_CKSUM_XOR; - } - - sbmp_frm_reset_tx(frm); - - frm->tx_cksum_type = cksum_type; - frm->tx_remain = length; - frm->tx_status = FRM_STATE_PAYLOAD; - - // Send the header - - uint16_t len = (uint16_t) length; - - uint8_t hdr[4] = { - 0x01, - cksum_type, - len & 0xFF, - (len >> 8) & 0xFF - }; - - uint8_t hdr_xor = 0; - for (int i = 0; i < 4; i++) { - hdr_xor ^= hdr[i]; - frm->tx_func(hdr[i]); - } - - frm->tx_func(hdr_xor); - - cksum_begin(frm->tx_cksum_type, &frm->tx_cksum_scratch); - - return true; -} - -/** End frame and enter idle mode */ -static void FLASH_FN end_frame(SBMP_FrmInst *frm) -{ - if (!frm->tx_enabled) { - sbmp_error("Can't tx, not enabled."); - return; - } - - cksum_end(frm->tx_cksum_type, &frm->tx_cksum_scratch); - - uint32_t cksum = frm->tx_cksum_scratch; - - switch (frm->tx_cksum_type) { - case SBMP_CKSUM_NONE: - break; // do nothing - - case SBMP_CKSUM_XOR: - // 1-byte checksum - frm->tx_func(cksum & 0xFF); - break; - - case SBMP_CKSUM_CRC32: - frm->tx_func(cksum & 0xFF); - frm->tx_func((cksum >> 8) & 0xFF); - frm->tx_func((cksum >> 16) & 0xFF); - frm->tx_func((cksum >> 24) & 0xFF); - } - - frm->tx_status = FRM_STATE_IDLE; // tx done -} - -/** Send a byte in the currently open frame */ -bool FLASH_FN sbmp_frm_send_byte(SBMP_FrmInst *frm, uint8_t byte) -{ - if (!frm->tx_enabled) { - sbmp_error("Can't tx, not enabled."); - return false; - } - - if (frm->tx_remain == 0 || frm->tx_status != FRM_STATE_PAYLOAD) { - return false; - } - - frm->tx_func(byte); - cksum_update(frm->tx_cksum_type, &frm->tx_cksum_scratch, byte); - frm->tx_remain--; - - if (frm->tx_remain == 0) { - end_frame(frm); // checksum & go idle - } - - return true; -} - -/** Send a buffer in the currently open frame */ -uint16_t FLASH_FN sbmp_frm_send_buffer(SBMP_FrmInst *frm, const uint8_t *buffer, uint16_t length) -{ - if (! frm->tx_enabled) { - sbmp_error("Can't tx, not enabled."); - return false; - } - - if (frm->tx_status != FRM_STATE_PAYLOAD) { - return false; // invalid call - } - - if (length == 0) { - end_frame(frm); // checksum & go idle - return 0; - } - - if (frm->tx_remain == 0) { - return false; // write past EOF (this shouldn't happen) - } - - uint16_t remain = length; - while (frm->tx_status == FRM_STATE_PAYLOAD && remain-- > 0) { - if (! sbmp_frm_send_byte(frm, *buffer++)) { - remain++; // "push back" - break; - } - } - - return (length - remain); -} diff --git a/sbmp-/sbmp_frame.h b/sbmp-/sbmp_frame.h deleted file mode 100644 index ce7ef99..0000000 --- a/sbmp-/sbmp_frame.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef SBMP_FRAME_H -#define SBMP_FRAME_H - -/** - * SBMP Frame parser. - * - * This is the lowest level of the SBMP stack. - * - * You can use the frame parser on it's own, if you don't the higher layers. - * You will still get checksums and other benefits. - */ - -#include -#include -#include - -#include "sbmp_config.h" -#include "sbmp_checksum.h" - -/** - * Status returned from the byte rx function. - */ -typedef enum { - SBMP_RX_OK = 0, /*!< Byte received */ - SBMP_RX_BUSY, /*!< SBMP busy with the last packet, try again */ - SBMP_RX_INVALID, /*!< The byte was rejected - can be ASCII debug, or just garbage. */ - SBMP_RX_DISABLED, /*!< The byte was rejected, because the frame parser is not enabled yet. */ -} SBMP_RxStatus; - -/** SBMP internal state (context). Allows having multiple SBMP interfaces. */ -typedef struct SBMP_FrmInstance_struct SBMP_FrmInst; - - -/** - * @brief Initialize the SBMP internal state struct - * - * @param frm : Pointer to the state struct to populate. NULL to allocate. - * @param buffer : Buffer for Rx. NULL to allocate. - * @param buffer_size : size of the Rx buffer (or how many bytes to allocate) - * @param rx_handler : callback when frame is received - * @param tx_func : function for sending bytes (USART Tx) - * @return pointer to the state struct (passed or allocated) - */ -SBMP_FrmInst *sbmp_frm_init( - SBMP_FrmInst *frm_or_null, - uint8_t *buffer_or_null, - uint16_t buffer_size, - void (*rx_handler)(uint8_t *payload, uint16_t length, void *user_token), - void (*tx_func)(uint8_t byte) -); - -/** - * @brief Set the user token value. - * - * The token will be passed to the Frame Rx callback. - * Can be used to identify higher level layer instance. - * - * If the token is not set, NULL will be used in the callback. - * - * @param frm : Framing layer instance - * @param token : pointer to arbitrary object. - */ -void sbmp_frm_set_user_token(SBMP_FrmInst *frm, void *token); - -/** - * @brief Reset the SBMP frm state, discard partial messages (both rx and tx). - * @param frm : Framing layer instance - */ -void sbmp_frm_reset(SBMP_FrmInst *frm); - -/** Reset the receiver state only */ -void sbmp_frm_reset_rx(SBMP_FrmInst *frm); - -/** Reset the transmitter state only */ -void sbmp_frm_reset_tx(SBMP_FrmInst *frm); - -/** - * @brief Enable or disable both Rx and Tx - * @param frm : Framing layer instance - * @param enable : true - enable, false - disable - */ -void sbmp_frm_enable(SBMP_FrmInst *frm, bool enable); - -/** - * @brief Enable or disable Rx & the frame parser - * @param frm : Framing layer instance - * @param enable_rx : true - enable, false - disable - */ -void sbmp_frm_enable_rx(SBMP_FrmInst *frm, bool enable_rx); - -/** - * @brief Enable or disable the frame builder & Tx - * @param frm : Framing layer instance - * @param enable_tx : true - enable, false - disable - */ -void sbmp_frm_enable_tx(SBMP_FrmInst *frm, bool enable_tx); - -/** - * @brief Handle an incoming byte - * - * @param frm : Framing layer instance - * @param rxbyte : byte received - * @return status - */ -SBMP_RxStatus sbmp_frm_receive(SBMP_FrmInst *frm, uint8_t rxbyte); - -/** - * @brief Start a frame transmission - * - * @param frm : Framing layer instance - * @param cksum_type : checksum to use (0, 32) - * @param length : payload length - * @return true if frame was started. - */ -bool sbmp_frm_start(SBMP_FrmInst *frm, SBMP_CksumType cksum_type, uint16_t length); - -/** - * @brief Send one byte in the open frame. - * - * If the payload was completed, checksum is be added and - * the frame is closed. - * - * @param frm : Framing layer instance - * @param byte : byte to send - * @return true on success (value did fit in a frame) - */ -bool sbmp_frm_send_byte(SBMP_FrmInst *frm, uint8_t byte); - -/** - * @brief Send a data buffer (or a part). - * - * If the payload was completed, checksum is be added and - * the frame is closed. - * - * @param frm : Framing layer instance - * @param buffer : buffer of bytes to send - * @param length : buffer length (byte count) - * @return actual sent length (until payload is full) - */ -uint16_t sbmp_frm_send_buffer(SBMP_FrmInst *frm, const uint8_t *buffer, uint16_t length); - - - -// ---- Internal frame struct ------------------------ - -/** SBMP framing layer Rx / Tx state */ -enum SBMP_FrmStatus { - FRM_STATE_IDLE, /*!< Ready to start/accept a frame */ - FRM_STATE_CKSUM_TYPE, /*!< Rx, waiting for checksum type (1 byte) */ - FRM_STATE_LENGTH, /*!< Rx, waiting for payload length (2 bytes) */ - FRM_STATE_HDRXOR, /*!< Rx, waiting for header XOR (1 byte) */ - FRM_STATE_PAYLOAD, /*!< Rx or Tx, payload rx/tx in progress. */ - FRM_STATE_DISCARD, /*!< Discard rx_length worth of bytes, then end */ - FRM_STATE_CKSUM, /*!< Rx, waiting for checksum (4 bytes) */ - FRM_STATE_WAIT_HANDLER, /*!< Rx, waiting for rx callback to process the payload */ -}; - -/** - * Internal state of the SBMP node - * Placed in the header to allow static allocation. - */ -struct SBMP_FrmInstance_struct { - - // --- reception --- - - uint32_t mb_buf; /*!< Multi-byte value buffer */ - uint8_t mb_cnt; - - uint8_t rx_hdr_xor; /*!< Header xor scratch field */ - - enum SBMP_FrmStatus rx_status; - - bool rx_enabled; /*!< Enable Rx. Disabled -> reject incoming bytes. */ - bool tx_enabled; /*!< Enable Rx. Disabled -> reject incoming bytes. */ - - uint8_t *rx_buffer; /*!< Incoming packet buffer */ - uint16_t rx_buffer_i; /*!< Buffer cursor */ - uint16_t rx_buffer_cap; /*!< Buffer capacity */ - - uint16_t rx_length; /*!< Total payload length */ - - SBMP_CksumType rx_cksum_type; /*!< Current packet's checksum type */ - uint32_t rx_cksum_scratch; /*!< crc aggregation field for received data */ - - void (*rx_handler)(uint8_t *payload, uint16_t length, void *user_token); /*!< Message received handler */ - - void *user_token; /*!< Arbitrary pointer set by the user. Passed to callbacks. - Can be used to identify instance of a higher layer. */ - - // --- transmission --- - - uint16_t tx_remain; /*!< Number of remaining bytes to transmit */ - SBMP_CksumType tx_cksum_type; - uint32_t tx_cksum_scratch; /*!< crc aggregation field for transmit */ - - enum SBMP_FrmStatus tx_status; - - // output functions. Only tx_func is needed. - void (*tx_func)(uint8_t byte); /*!< Function to send one byte */ -}; - -// ------------------------------------ - - -#endif /* SBMP_FRAME_H */ diff --git a/sbmp-/sbmp_logging.h b/sbmp-/sbmp_logging.h deleted file mode 100644 index 9cf4406..0000000 --- a/sbmp-/sbmp_logging.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SBMP_COMMON_H -#define SBMP_COMMON_H - -#include "sbmp_config.h" -#include "esp8266.h" - -/** - * SBMP logging utils - */ - -// do-nothing definitions -#define sbmp_error(fmt, ...) os_printf("\x1b[31;1mSBMP][E] "fmt"\x1b[0m\r\n", ##__VA_ARGS__) -#define sbmp_info(fmt, ...) os_printf("\x1b[32;1m[SBMP][i] "fmt"\x1b[0m\r\n", ##__VA_ARGS__) - -#endif /* SBMP_COMMON_H */ diff --git a/sbmp-/sbmp_session.c b/sbmp-/sbmp_session.c deleted file mode 100644 index 5fa16ec..0000000 --- a/sbmp-/sbmp_session.c +++ /dev/null @@ -1,416 +0,0 @@ -#include "esp8266.h" - -#include "sbmp_config.h" -#include "sbmp_logging.h" -#include "sbmp_session.h" - -// protos -static void handle_hsk_datagram(SBMP_Endpoint *ep, SBMP_Datagram *dg); - -// lsb, msb for uint16_t -#define U16_LSB(x) ((x) & 0xFF) -#define U16_MSB(x) ((x >> 8) & 0xFF) - -// length of the payload sent with a handshake packet. -#define HSK_PAYLOAD_LEN 3 -// Datagram header length - 2 B sesn, 1 B type -#define DATAGRA_HEADER_LEN 3 - - -/** Rx handler that is assigned to the framing layer */ -static void FLASH_FN ep_rx_handler(uint8_t *buf, uint16_t len, void *token) -{ - // endpoint pointer is stored in the user token - SBMP_Endpoint *ep = (SBMP_Endpoint *)token; - - if (NULL != sbmp_dg_parse(&ep->static_dg, buf, len)) { - // payload parsed OK - - // check if handshake datagram, else call user callback. - handle_hsk_datagram(ep, &ep->static_dg); - } -} - -/** - * @brief Initialize the endpoint. - * - * @param ep : Endpoint var pointer, or NULL to allocate one. - * @param buffer : Rx buffer. NULL to allocate one. - * @param buffer_size : Rx buffer length - * @return the endpoint struct pointer (allocated if ep was NULL) - */ -SBMP_Endpoint FLASH_FN *sbmp_ep_init( - SBMP_Endpoint *ep, - uint8_t *buffer, - uint16_t buffer_size, - void (*dg_rx_handler)(SBMP_Datagram *dg), - void (*tx_func)(uint8_t byte)) -{ - if (ep == NULL) { - // request to allocate it - #if SBMP_MALLOC - ep = malloc(sizeof(SBMP_Endpoint)); - #else - return NULL; // fail - #endif - } - - // set up the framing layer - sbmp_frm_init(&ep->frm, buffer, buffer_size, ep_rx_handler, tx_func); - - // set token, so callback knows what EP it's for. - sbmp_frm_set_user_token(&ep->frm, (void *) ep); - - ep->rx_handler = dg_rx_handler; - ep->buffer_size = buffer_size; // sent to the peer - -#if SBMP_HAS_CRC32 - ep->peer_pref_cksum = SBMP_CKSUM_CRC32; - ep->pref_cksum = SBMP_CKSUM_CRC32; -#else - ep->peer_pref_cksum = SBMP_CKSUM_XOR; - ep->pref_cksum = SBMP_CKSUM_XOR; -#endif - - // reset state information - sbmp_ep_reset(ep); - - return ep; -} - -/** - * @brief Reset an endpoint and it's Framing Layer - * - * This discards all state information. - * - * @param ep : Endpoint - */ -void FLASH_FN sbmp_ep_reset(SBMP_Endpoint *ep) -{ - ep->next_session = 0; - ep->origin = 0; - - // init the handshake status - ep->hsk_session = 0; - ep->hsk_state = SBMP_HSK_NOT_STARTED; - - ep->peer_buffer_size = 0xFFFF; // max possible buffer - - sbmp_frm_reset(&ep->frm); -} - - -// --- Customizing settings --- - -/** Set session number (good to randomize before first message) */ -void FLASH_FN sbmp_ep_seed_session(SBMP_Endpoint *ep, uint16_t sesn) -{ - ep->next_session = sesn & 0x7FFF; -} - -/** Set the origin bit (bypass handshake) */ -void FLASH_FN sbmp_ep_set_origin(SBMP_Endpoint *endp, bool bit) -{ - endp->origin = bit; -} - -/** Set the preferred checksum. */ -void FLASH_FN sbmp_ep_set_preferred_cksum(SBMP_Endpoint *endp, SBMP_CksumType cksum_type) -{ - if (cksum_type == SBMP_CKSUM_CRC32 && !SBMP_HAS_CRC32) { - sbmp_error("CRC32 not avail, using XOR instead."); - cksum_type = SBMP_CKSUM_XOR; - } - - endp->pref_cksum = cksum_type; -} - - -/** Enable or disable RX in the FrmInst backing this Endpoint */ -void FLASH_FN sbmp_ep_enable_rx(SBMP_Endpoint *ep, bool enable_rx) -{ - sbmp_frm_enable_rx(&ep->frm, enable_rx); -} - -/** Enable or disable TX in the FrmInst backing this Endpoint */ -void FLASH_FN sbmp_ep_enable_tx(SBMP_Endpoint *ep, bool enable_tx) -{ - sbmp_frm_enable_tx(&ep->frm, enable_tx); -} - -/** Enable or disable Rx & TX in the FrmInst backing this Endpoint */ -void FLASH_FN sbmp_ep_enable(SBMP_Endpoint *ep, bool enable) -{ - sbmp_frm_enable(&ep->frm, enable); -} - -// --- - -/** Get a new session number */ -static uint16_t FLASH_FN next_session(SBMP_Endpoint *ep) -{ - uint16_t sesn = ep->next_session; - - if (++ep->next_session == 0x8000) { - // overflow into the origin bit - ep->next_session = 0; // start from zero - } - - return sesn | (uint16_t)(ep->origin << 15); // add the origin bit -} - - -// --- Header/body send funcs --- - -/** Start a message as a reply */ -bool FLASH_FN sbmp_ep_start_response(SBMP_Endpoint *ep, SBMP_DgType type, uint16_t length, uint16_t sesn) -{ - uint16_t peer_accepts = ep->peer_buffer_size - DATAGRA_HEADER_LEN; - - if (length > peer_accepts) { - sbmp_error("Msg too long (%d B), peer accepts max %d B.", length, peer_accepts); - return false; - } - - return sbmp_dg_start(&ep->frm, ep->peer_pref_cksum, sesn, type, length); -} - -/** Start a message in a new session */ -bool FLASH_FN sbmp_ep_start_session(SBMP_Endpoint *ep, SBMP_DgType type, uint16_t length, uint16_t *sesn_ptr) -{ - uint16_t sn = next_session(ep); - - bool suc = sbmp_ep_start_response(ep, type, length, sn); - if (suc) { - if (sesn_ptr != NULL) *sesn_ptr = sn; - } - - return suc; -} - -/** Send one byte in the current message */ -bool FLASH_FN sbmp_ep_send_byte(SBMP_Endpoint *ep, uint8_t byte) -{ - return sbmp_frm_send_byte(&ep->frm, byte); -} - -/** Send a data buffer (or a part) in the current message */ -uint16_t FLASH_FN sbmp_ep_send_buffer(SBMP_Endpoint *ep, const uint8_t *buffer, uint16_t length) -{ - return sbmp_frm_send_buffer(&ep->frm, buffer, length); -} - -/** Rx, pass to framing layer */ -SBMP_RxStatus FLASH_FN sbmp_ep_receive(SBMP_Endpoint *ep, uint8_t byte) -{ - return sbmp_frm_receive(&ep->frm, byte); -} - - -// --- All-in-one send funcs --- - -/** Send a message in a session. */ -bool FLASH_FN sbmp_ep_send_response( - SBMP_Endpoint *ep, - SBMP_DgType type, - const uint8_t *buffer, - uint16_t length, - uint16_t sesn, - uint16_t *sent_bytes_ptr) -{ - bool suc = sbmp_ep_start_response(ep, type, length, sesn); - - if (suc) { - uint16_t sent = sbmp_ep_send_buffer(ep, buffer, length); - - if (sent_bytes_ptr != NULL) *sent_bytes_ptr = sent; - } - - return suc; -} - -/** Send message in a new session */ -bool FLASH_FN sbmp_ep_send_message( - SBMP_Endpoint *ep, - SBMP_DgType type, - const uint8_t *buffer, - uint16_t length, - uint16_t *sesn_ptr, - uint16_t *sent_bytes_ptr) -{ - // This juggling with session nr is because it wouldn't work - // without actual hardware delay otherwise. - - uint16_t sn = next_session(ep);; - - uint16_t old_sesn = 0; - if (sesn_ptr != NULL) { - old_sesn = *sesn_ptr; - *sesn_ptr = sn; - } - - bool suc = sbmp_ep_send_response(ep, type, buffer, length, sn, sent_bytes_ptr); - - if (!suc) { - if (sesn_ptr != NULL) { - *sesn_ptr = old_sesn; // restore - } - } - - return suc; -} - - -// --- Handshake --- -/** - * Prepare a buffer to send to peer during handshake - * - * The buffer is long HSK_PAYLOAD_LEN bytes - */ -static void FLASH_FN populate_hsk_buf(SBMP_Endpoint *ep, uint8_t* buf) -{ - // [ pref_crc 1B | buf_size 2B ] - - buf[0] = ep->pref_cksum; - buf[1] = U16_LSB(ep->buffer_size); - buf[2] = U16_MSB(ep->buffer_size); -} - -/** Parse peer info from received handhsake dg payload */ -static void FLASH_FN parse_peer_hsk_buf(SBMP_Endpoint *ep, const uint8_t* buf) -{ - ep->peer_pref_cksum = buf[0]; - ep->peer_buffer_size = (uint16_t)(buf[1] | (buf[2] << 8)); - - sbmp_info("HSK success, peer buf %d, pref cksum %d", - ep->peer_buffer_size, - ep->peer_pref_cksum); - - // check if checksum available - if (ep->peer_pref_cksum == SBMP_CKSUM_CRC32 && !SBMP_HAS_CRC32) { - sbmp_error("CRC32 not avail, using XOR as peer's pref cksum."); - ep->peer_pref_cksum = SBMP_CKSUM_XOR; - } -} - -/** - * @brief Start a handshake (origin bit arbitration) - * @param ep : Endpoint state - */ -bool FLASH_FN sbmp_ep_start_handshake(SBMP_Endpoint *ep) -{ - if (ep->hsk_state == SBMP_HSK_AWAIT_REPLY) { - // busy now - sbmp_error("Can't start HSK, in progress already."); - return false; - } - - ep->hsk_state = 0; - - uint8_t buf[HSK_PAYLOAD_LEN]; - populate_hsk_buf(ep, buf); - - ep->hsk_state = SBMP_HSK_AWAIT_REPLY; - - bool suc = sbmp_ep_send_message(ep, SBMP_DG_HSK_START, buf, 3, &ep->hsk_session, NULL); - - if (!suc) { - ep->hsk_state = SBMP_HSK_NOT_STARTED; - } - - return suc; -} - -/** Get hsk state */ -SBMP_HandshakeStatus FLASH_FN sbmp_ep_handshake_status(SBMP_Endpoint *ep) -{ - return ep->hsk_state; -} - -/** - * @brief Process handshake datagrams & update handshake state accordingly. - * - * Non-handshake datagrams are passed on to the user Rx callback. - * - * @param ep : endpoint - * @param dg : datagram - */ -static void FLASH_FN handle_hsk_datagram(SBMP_Endpoint *ep, SBMP_Datagram *dg) -{ - bool hsk_start = (dg->type == SBMP_DG_HSK_START); - bool hsk_accept = (dg->type == SBMP_DG_HSK_ACCEPT); - bool hsk_conflict = (dg->type == SBMP_DG_HSK_CONFLICT); - - if (hsk_start || hsk_accept || hsk_conflict) { - // prepare payload to send in response - uint8_t our_info_pld[HSK_PAYLOAD_LEN]; - populate_hsk_buf(ep, our_info_pld); - - //printf("hsk_state = %d, hsk_ses %d, dg_ses %d\n",ep->hsk_state, ep->hsk_session, dg->session); - - if (hsk_start) { - // peer requests origin - sbmp_info("Rx HSK request"); - - if (ep->hsk_state == SBMP_HSK_AWAIT_REPLY) { - // conflict occured - we're already waiting for a reply. - sbmp_ep_send_response(ep, SBMP_DG_HSK_CONFLICT, our_info_pld, HSK_PAYLOAD_LEN, dg->session, NULL); - ep->hsk_state = SBMP_HSK_CONFLICT; - - sbmp_error("HSK conflict"); - } else { - // we're idle, accept the request. - bool peer_origin = (dg->session & 0x8000) >> 15; - sbmp_ep_set_origin(ep, !peer_origin); - - // read peer's info - if (dg->length >= HSK_PAYLOAD_LEN) { - parse_peer_hsk_buf(ep, dg->payload); - } - - ep->hsk_state = SBMP_HSK_SUCCESS; - - // Send Accept response - sbmp_ep_send_response(ep, SBMP_DG_HSK_ACCEPT, our_info_pld, HSK_PAYLOAD_LEN, dg->session, NULL); - } - } else if (hsk_accept) { - // peer accepted our request - sbmp_info("Rx HSK accept"); - - if (ep->hsk_state != SBMP_HSK_AWAIT_REPLY || ep->hsk_session != dg->session) { - // but we didn't send any request - sbmp_error("Rx unexpected HSK accept, ignoring."); - - } else { - // OK, we were waiting for this reply - - // read peer's info - if (dg->length >= HSK_PAYLOAD_LEN) { - parse_peer_hsk_buf(ep, dg->payload); - } - - ep->hsk_state = SBMP_HSK_SUCCESS; - } - } else if (hsk_conflict) { - // peer rejected our request due to conflict - sbmp_info("Rx HSK conflict"); - - if (ep->hsk_state != SBMP_HSK_AWAIT_REPLY || ep->hsk_session != dg->session) { - // but we didn't send any request - sbmp_error("Rx unexpected HSK conflict, ignoring."); - } else { - // Acknowledge the conflict - - // reset everything - sbmp_frm_reset(&ep->frm); - - ep->hsk_state = SBMP_HSK_CONFLICT; - } - } - - } else { - // Not a HSK message - ep->rx_handler(dg); - } -} - diff --git a/sbmp-/sbmp_session.h b/sbmp-/sbmp_session.h deleted file mode 100644 index b967d6f..0000000 --- a/sbmp-/sbmp_session.h +++ /dev/null @@ -1,207 +0,0 @@ -#ifndef SBMP_SESSION_H -#define SBMP_SESSION_H - -/** - * SBMP session layer - * - * This layer provides an abstraction over all of SBMP. - * - * Start by creating "endpoint" with sbmp_ep_init(), then configure and enable it. - * - * Next you should trigger a handshake, which assigns your endpoint the origin bit, - * and obtains information about your peer (it's buffer size and preferred checksum). - * - * You can still interact with the framing layer directly, but it shouldn't be needed. - */ - -#include -#include -#include - -#include "sbmp_config.h" -#include "sbmp_datagram.h" -#include "sbmp_frame.h" - -typedef enum { - SBMP_HSK_NOT_STARTED = 0, /*!< Initial state, unconfigured */ - SBMP_HSK_SUCCESS = 1, /*!< Handshake done, origin assigned. */ - SBMP_HSK_AWAIT_REPLY = 2, /*!< Request sent, awaiting a reply */ - SBMP_HSK_CONFLICT = 3, /*!< Conflict occured during HSK */ -} SBMP_HandshakeStatus; - - -/** SBMP Endpoint (session) structure */ -typedef struct { - bool origin; /*!< Local origin bit */ - uint16_t next_session; /*!< Next session number */ - - void (*rx_handler)(SBMP_Datagram *dg); /*!< Datagram receive handler */ - - SBMP_FrmInst frm; /*!< Framing layer internal state */ - - // Handshake - SBMP_HandshakeStatus hsk_state; /*!< Handshake progress */ - uint16_t hsk_session; /*!< Session number of the handshake request message */ - uint16_t peer_buffer_size; /*!< Peer's buffer size (obtained during handshake) */ - SBMP_CksumType peer_pref_cksum; /*!< Peer's preferred checksum type */ - - // Our info for the peer - uint16_t buffer_size; /*!< Our buffer size */ - SBMP_CksumType pref_cksum; /*!< Our preferred checksum */ - - SBMP_Datagram static_dg; /*!< Static datagram, used when DG is pased to a callback. - This way the datagram remains valid until next Frm Rx, - not only until the callback ends. Disabling the EP in the Rx - callback lets you preserve the Dg for a longer period - - i.e. put it in a global var, where a loop retrieves it. */ -} SBMP_Endpoint; - - -/** - * @brief Initialize the endpoint. - * - * @note about the Rx handler: - * The datagram is valid until a new payload byte is received by the Frm. - * Disable the endpoint (-> thus also Frm) in the callback if you need - * to keep the Dg longer. Then re-enable it after the Dg is processed. - * - * @param ep : Endpoint struct pointer, or NULL to allocate one. - * @param buffer : Rx buffer. NULL to allocate one. - * @param buffer_size : Rx buffer length - * @param dg_rx_handler : Datagram received handler. - * @param tx_func : Function to send a byte to USART - * @return the endpoint struct pointer (allocated if ep was NULL) - */ -SBMP_Endpoint *sbmp_ep_init(SBMP_Endpoint *ep, - uint8_t *buffer, - uint16_t buffer_size, - void (*dg_rx_handler)(SBMP_Datagram *dg), - void (*tx_func)(uint8_t byte)); - -/** - * @brief Reset an endpoint and it's Framing Layer - * - * This discards all state information. - * - * @param ep : Endpoint - */ -void sbmp_ep_reset(SBMP_Endpoint *ep); - -/** Set session number (good to randomize before starting a handshake) */ -void sbmp_ep_seed_session(SBMP_Endpoint *ep, uint16_t sesn); - -/** - * Set the origin bit. - * This can be used instead of handshake if origins are pre-assigned. - */ -void sbmp_ep_set_origin(SBMP_Endpoint *endp, bool bit); - -/** Set the preferred checksum for this peer. */ -void sbmp_ep_set_preferred_cksum(SBMP_Endpoint *endp, SBMP_CksumType cksum_type); - -/** - * @brief Start a message as a reply, with CRC32 - * - * @param ep : Endpoint struct - * @param type : Datagram type ID - * @param length : Datagram payload length (bytes) - * @param sesn : Session number of message this is a reply to. - * @return success - */ -bool sbmp_ep_start_response(SBMP_Endpoint *ep, SBMP_DgType type, uint16_t length, uint16_t sesn); - -/** - * @brief Start a message in a new session, with CRC32 - * - * @param ep : Endpoint struct - * @param type : Datagram type ID - * @param length : Datagram payload length (bytes) - * @param sesn : Var to store session number, NULL = don't store. - * @return success - */ -bool sbmp_ep_start_session(SBMP_Endpoint *ep, SBMP_DgType type, uint16_t length, uint16_t *sesn_ptr); - -/** - * @brief Send one byte in the current message - * - * @param ep : Endpoint struct - * @param byte : byte to send - * @return true on success - */ -bool sbmp_ep_send_byte(SBMP_Endpoint *ep, uint8_t byte); - -/** - * @brief Send a data buffer (or a part) in the current message - * - * @param ep : Endpoint struct - * @param buffer : buffer of bytes to send - * @param length : buffer length (byte count) - * @return actual sent length (until payload is full) - */ -uint16_t sbmp_ep_send_buffer(SBMP_Endpoint *ep, const uint8_t *buffer, uint16_t length); - -/** - * @brief Send a message in a new session. - * - * @param ep : Endpoint struct - * @param type : Datagram type ID - * @param buffer : Buffer with data to send - * @param length : Datagram payload length (bytes) - * @param sesn_ptr : Session number - * @param sent_bytes_ptr : Var to store NR of sent bytes. NULL = don't store. - * @return success - */ -bool sbmp_ep_send_response( - SBMP_Endpoint *ep, - SBMP_DgType type, - const uint8_t *buffer, - uint16_t length, - uint16_t sesn_ptr, - uint16_t *sent_bytes_ptr); - -/** - * @brief Send a message in a new session. - * - * @param ep : Endpoint struct - * @param type : Datagram type ID - * @param buffer : Buffer with data to send - * @param length : Datagram payload length (bytes) - * @param sesn_ptr : Var to store session number. NULL = don't store. - * @param sent_bytes_ptr : Var to store NR of sent bytes. NULL = don't store. - * @return success - */ -bool sbmp_ep_send_message( - SBMP_Endpoint *ep, - SBMP_DgType type, - const uint8_t *buffer, - uint16_t length, - uint16_t *sesn, - uint16_t *sent_bytes); - -/** - * @brief Start a handshake (origin bit arbitration) - * @param ep : Endpoint struct - */ -bool sbmp_ep_start_handshake(SBMP_Endpoint *ep); - -/** - * @brief Receive a byte from USART (is passed to the framing layer) - * @param ep : Endpoint struct - * @param byte : Byte received from USART - * @return true if byte was consumed - */ -SBMP_RxStatus sbmp_ep_receive(SBMP_Endpoint *ep, uint8_t byte); - -/** Get current handshake state */ -SBMP_HandshakeStatus sbmp_ep_handshake_status(SBMP_Endpoint *ep); - -/** Enable or disable both Rx and TX in the FrmInst backing this Endpoint */ -void sbmp_ep_enable(SBMP_Endpoint *ep, bool enable); - -/** Enable or disable RX in the FrmInst backing this Endpoint */ -void sbmp_ep_enable_rx(SBMP_Endpoint *ep, bool enable_rx); - -/** Enable or disable TX in the FrmInst backing this Endpoint */ -void sbmp_ep_enable_tx(SBMP_Endpoint *ep, bool enable_tx); - -#endif /* SBMP_SESSION_H */