diff --git a/README.md b/README.md index 26e6c01..08103c2 100644 --- a/README.md +++ b/README.md @@ -85,21 +85,6 @@ if (rsp != NULL) { } ``` -## Keeping up to date with note-c repo - -This library depends on the Blues [`note-c` library][note-c]. To update this -repo with the latest from `note-c`, run the `update_note_c.sh` shell script -from the `scripts/` folder: - -```none -scripts/update_note_c.sh -``` - -_**NOTE:** It is important to use the script. It utilizes git subtrees to -include the appropriate files in the `src/note-c` folder. It also eliminates -folders that necessary for testing `note-c` individually, but interfere with -the Arduino build environment._ - ## Documentation The documentation for this library can be found @@ -260,7 +245,22 @@ at the end of the array, and syntax should be as follows, ## Generating a Release -### Update Files +### Update `note-c` dependency + +This library depends on the Blues [`note-c` library][note-c]. To update this +repo with the latest from `note-c`, run the `update_note_c.sh` shell script +from the `scripts/` folder: + +```none +scripts/update_note_c.sh +``` + +_**NOTE:** It is important to use the script. It utilizes git subtrees to +include the appropriate files in the `src/note-c` folder. It also eliminates +folders that necessary for testing `note-c` individually, but interfere with +the Arduino build environment._ + +### Update Version Files When generating a release of the `note-arduino` library, you will need to update the version in two places. @@ -281,12 +281,13 @@ the version in two places. version string should follow the form "\.\.\" (e.g. `1.6.4`). This value will be used by the Arduino Library Manager. -### GitHub Release +### Arduino Library Manager Release Publishing a release on GitHub will trigger the Arduino Library Manager. The -Arduino Library Manager will then look to the `library.properties` file, and -generate a release based on the `version` value it finds there. It should be -noted, the version on GitHub is not evaluated by the Arduino Library Manager. +Arduino Library Manager will look to the `library.properties` file, and generate +a release based solely on the `version` value it finds there. + +_**NOTE:** The GitHub version is not evaluated by the Arduino Library Manager._ ## More Information diff --git a/library.properties b/library.properties index 5c90b00..cdf6918 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Blues Wireless Notecard -version=1.6.5 +version=1.6.6 author=Blues maintainer=Blues sentence=An easy to use Notecard Library for Arduino. diff --git a/src/NoteDefines.h b/src/NoteDefines.h index e8191a8..520cef6 100644 --- a/src/NoteDefines.h +++ b/src/NoteDefines.h @@ -4,7 +4,7 @@ // Define the version of the `note-arduino` library #define NOTE_ARDUINO_VERSION_MAJOR 1 #define NOTE_ARDUINO_VERSION_MINOR 6 -#define NOTE_ARDUINO_VERSION_PATCH 5 +#define NOTE_ARDUINO_VERSION_PATCH 6 #define NOTE_ARDUINO_VERSION NOTE_C_STRINGIZE(NOTE_ARDUINO_VERSION_MAJOR) "." NOTE_C_STRINGIZE(NOTE_ARDUINO_VERSION_MINOR) "." NOTE_C_STRINGIZE(NOTE_ARDUINO_VERSION_PATCH) diff --git a/src/note-c/n_helpers.c b/src/note-c/n_helpers.c index ef9504c..f4535c5 100644 --- a/src/note-c/n_helpers.c +++ b/src/note-c/n_helpers.c @@ -529,8 +529,14 @@ const char * NoteBinaryStoreTransmit(uint8_t *unencodedData, uint32_t unencodedL return err; } - // Issue a "card.binary" request. - J *rsp = NoteRequestResponse(NoteNewRequest("card.binary")); + // Issue a "card.binary" request. The length is reset if this is the + // first segment, clearing out any error that might potentially be + // pending from a previous use of the binary store. + J *req = NoteNewRequest("card.binary"); + if (notecardOffset == 0) { + JAddBoolToObject(req, "reset", true); + } + J *rsp = NoteRequestResponse(req); if (!rsp) { const char *err = ERRSTR("unable to issue binary request", c_err); NOTE_C_LOG_ERROR(err); diff --git a/src/note-c/n_hooks.c b/src/note-c/n_hooks.c index a75df4d..933c460 100644 --- a/src/note-c/n_hooks.c +++ b/src/note-c/n_hooks.c @@ -18,9 +18,10 @@ */ #include -#include #include +#include #include + #include "n_lib.h" //**************************************************************************/ @@ -35,11 +36,6 @@ #include #endif -// Which I/O port to use -#define interfaceNone 0 -#define interfaceSerial 1 -#define interfaceI2C 2 - // Externalized Hooks //**************************************************************************/ /*! @@ -76,114 +72,180 @@ mutexFn hookUnlockNote = NULL; @brief Hook for the calling platform's transaction initiation function. */ /**************************************************************************/ -txnStartFn hookTransactionStart = NULL; +NOTE_C_STATIC txnStartFn hookTransactionStart = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's transaction completion function. */ /**************************************************************************/ -txnStopFn hookTransactionStop = NULL; +NOTE_C_STATIC txnStopFn hookTransactionStop = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's memory allocation function. */ /**************************************************************************/ -mallocFn hookMalloc = NULL; +NOTE_C_STATIC mallocFn hookMalloc = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's memory free function. */ /**************************************************************************/ -freeFn hookFree = NULL; +NOTE_C_STATIC freeFn hookFree = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's delay function. */ /**************************************************************************/ -delayMsFn hookDelayMs = NULL; +NOTE_C_STATIC delayMsFn hookDelayMs = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's millis timing function. */ /**************************************************************************/ -getMsFn hookGetMs = NULL; +NOTE_C_STATIC getMsFn hookGetMs = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's current active interface. Value is one of: - - interfaceNone = 0 (default) - - interfaceSerial = 1 - - interfaceI2C = 2 + - NOTE_C_INTERFACE_NONE (default) + - NOTE_C_INTERFACE_SERIAL + - NOTE_C_INTERFACE_I2C */ /**************************************************************************/ -uint32_t hookActiveInterface = interfaceNone; +NOTE_C_STATIC volatile int hookActiveInterface = NOTE_C_INTERFACE_NONE; //**************************************************************************/ /*! @brief Hook for the calling platform's Serial reset function. */ /**************************************************************************/ -serialResetFn hookSerialReset = NULL; +NOTE_C_STATIC serialResetFn hookSerialReset = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's Serial transmit function. */ /**************************************************************************/ -serialTransmitFn hookSerialTransmit = NULL; +NOTE_C_STATIC serialTransmitFn hookSerialTransmit = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's Serial data available function. */ /**************************************************************************/ -serialAvailableFn hookSerialAvailable = NULL; +NOTE_C_STATIC serialAvailableFn hookSerialAvailable = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's Serial receive function. */ /**************************************************************************/ -serialReceiveFn hookSerialReceive = NULL; - +NOTE_C_STATIC serialReceiveFn hookSerialReceive = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's I2C address. */ /**************************************************************************/ -uint32_t i2cAddress = 0; +NOTE_C_STATIC uint32_t i2cAddress = 0; //**************************************************************************/ /*! @brief Hook for the calling platform's I2C maximum segment size, in bytes. */ /**************************************************************************/ -uint32_t i2cMax = 0; +NOTE_C_STATIC uint32_t i2cMax = 0; //**************************************************************************/ /*! @brief Hook for the calling platform's I2C reset function. */ /**************************************************************************/ -i2cResetFn hookI2CReset = NULL; +NOTE_C_STATIC i2cResetFn hookI2CReset = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's transmit function. */ /**************************************************************************/ -i2cTransmitFn hookI2CTransmit = NULL; +NOTE_C_STATIC i2cTransmitFn hookI2CTransmit = NULL; //**************************************************************************/ /*! @brief Hook for the calling platform's I2C receive function. */ /**************************************************************************/ -i2cReceiveFn hookI2CReceive = NULL; +NOTE_C_STATIC i2cReceiveFn hookI2CReceive = NULL; +//**************************************************************************/ +/*! + @brief Variable used to determine the runtime logging level +*/ +/**************************************************************************/ +#ifndef NOTE_NODEBUG +NOTE_C_STATIC int noteLogLevel = NOTE_C_LOG_LEVEL; +#endif // Internal hooks typedef bool (*nNoteResetFn) (void); typedef const char * (*nTransactionFn) (const char *, size_t, char **, uint32_t); typedef const char * (*nReceiveFn) (uint8_t *, uint32_t *, bool, uint32_t, uint32_t *); typedef const char * (*nTransmitFn) (uint8_t *, uint32_t, bool); -static nNoteResetFn notecardReset = NULL; -static nTransactionFn notecardTransaction = NULL; -static nReceiveFn notecardChunkedReceive = NULL; -static nTransmitFn notecardChunkedTransmit = NULL; +NOTE_C_STATIC nNoteResetFn notecardReset = NULL; +NOTE_C_STATIC nTransactionFn notecardTransaction = NULL; +NOTE_C_STATIC nReceiveFn notecardChunkedReceive = NULL; +NOTE_C_STATIC nTransmitFn notecardChunkedTransmit = NULL; +//**************************************************************************/ +/*! + @brief Get the active, platform-specific communications method + + @returns The active interface. One of: + - NOTE_C_INTERFACE_NONE (default) + - NOTE_C_INTERFACE_SERIAL + - NOTE_C_INTERFACE_I2C + */ +/**************************************************************************/ +int NoteGetActiveInterface(void) +{ + return hookActiveInterface; +} + +NOTE_C_STATIC void _noteSetActiveInterface(int interface) +{ + hookActiveInterface = interface; + + switch (interface) { + case NOTE_C_INTERFACE_SERIAL: + notecardReset = _serialNoteReset; + notecardTransaction = _serialNoteTransaction; + notecardChunkedReceive = _serialChunkedReceive; + notecardChunkedTransmit = _serialChunkedTransmit; + break; + case NOTE_C_INTERFACE_I2C: + notecardReset = _i2cNoteReset; + notecardTransaction = _i2cNoteTransaction; + notecardChunkedReceive = _i2cNoteChunkedReceive; + notecardChunkedTransmit = _i2cNoteChunkedTransmit; + break; + default: + hookActiveInterface = NOTE_C_INTERFACE_NONE; // unrecognized interfaces are disabled + notecardReset = NULL; + notecardTransaction = NULL; + notecardChunkedReceive = NULL; + notecardChunkedTransmit = NULL; + break; + } +} + +//**************************************************************************/ +/*! + @brief Set the desired, platform-specific communications method + @param interface The desired interface to use. One of: + - NOTE_C_INTERFACE_NONE (default) + - NOTE_C_INTERFACE_SERIAL + - NOTE_C_INTERFACE_I2C + */ +/**************************************************************************/ +void NoteSetActiveInterface(int interface) +{ + _LockNote(); + _noteSetActiveInterface(interface); + _UnlockNote(); +} + +//**************************************************************************/ /*! @brief Set the default memory and timing hooks if they aren't already set @param mallocfn The default memory allocation `malloc` @@ -193,8 +255,10 @@ static nTransmitFn notecardChunkedTransmit = NULL; @param delayfn The default delay function to use. @param millisfn The default 'millis' function to use. */ +//**************************************************************************/ void NoteSetFnDefault(mallocFn mallocfn, freeFn freefn, delayMsFn delayfn, getMsFn millisfn) { + _LockNote(); if (hookMalloc == NULL) { hookMalloc = mallocfn; } @@ -207,8 +271,10 @@ void NoteSetFnDefault(mallocFn mallocfn, freeFn freefn, delayMsFn delayfn, getMs if (hookGetMs == NULL) { hookGetMs = millisfn; } + _UnlockNote(); } +//**************************************************************************/ /*! @brief Set the platform-specific memory and timing hooks. @@ -218,13 +284,16 @@ void NoteSetFnDefault(mallocFn mallocfn, freeFn freefn, delayMsFn delayfn, getMs @param delayMsHook The platform-specific millisecond delay function. @param getMsHook The platform-specific millisecond counter function. */ +//**************************************************************************/ void NoteSetFn(mallocFn mallocHook, freeFn freeHook, delayMsFn delayMsHook, getMsFn getMsHook) { + _LockNote(); hookMalloc = mallocHook; hookFree = freeHook; hookDelayMs = delayMsHook; hookGetMs = getMsHook; + _UnlockNote(); } //**************************************************************************/ @@ -235,7 +304,9 @@ void NoteSetFn(mallocFn mallocHook, freeFn freeHook, delayMsFn delayMsHook, /**************************************************************************/ void NoteSetFnDebugOutput(debugOutputFn fn) { + _LockNote(); hookDebugOutput = fn; + _UnlockNote(); } //**************************************************************************/ @@ -260,8 +331,10 @@ bool _noteIsDebugOutputActive(void) /**************************************************************************/ void NoteSetFnTransaction(txnStartFn startFn, txnStopFn stopFn) { + _LockNote(); hookTransactionStart = startFn; hookTransactionStop = stopFn; + _UnlockNote(); } //**************************************************************************/ @@ -319,17 +392,16 @@ void NoteSetFnNoteMutex(mutexFn lockFn, mutexFn unlockFn) void NoteSetFnSerial(serialResetFn resetFn, serialTransmitFn transmitFn, serialAvailableFn availFn, serialReceiveFn receiveFn) { - hookActiveInterface = interfaceSerial; + _LockNote(); hookSerialReset = resetFn; hookSerialTransmit = transmitFn; hookSerialAvailable = availFn; hookSerialReceive = receiveFn; - notecardReset = _serialNoteReset; - notecardTransaction = _serialNoteTransaction; - notecardChunkedReceive = _serialChunkedReceive; - notecardChunkedTransmit = _serialChunkedTransmit; + _noteSetActiveInterface(NOTE_C_INTERFACE_SERIAL); + + _UnlockNote(); } /*! @@ -350,19 +422,18 @@ void NoteSetFnI2C(uint32_t notecardAddr, uint32_t maxTransmitSize, i2cResetFn resetFn, i2cTransmitFn transmitFn, i2cReceiveFn receiveFn) { + _LockNote(); + i2cAddress = notecardAddr; i2cMax = maxTransmitSize; - hookActiveInterface = interfaceI2C; - hookI2CReset = resetFn; hookI2CTransmit = transmitFn; hookI2CReceive = receiveFn; - notecardReset = _i2cNoteReset; - notecardTransaction = _i2cNoteTransaction; - notecardChunkedReceive = _i2cChunkedReceive; - notecardChunkedTransmit = _i2cChunkedTransmit; + _noteSetActiveInterface(NOTE_C_INTERFACE_I2C); + + _UnlockNote(); } //**************************************************************************/ @@ -373,26 +444,14 @@ void NoteSetFnI2C(uint32_t notecardAddr, uint32_t maxTransmitSize, void NoteSetFnDisabled(void) { - hookActiveInterface = interfaceNone; - - notecardReset = NULL; - notecardTransaction = NULL; - notecardChunkedReceive = NULL; - notecardChunkedTransmit = NULL; + _LockNote(); + _noteSetActiveInterface(NOTE_C_INTERFACE_NONE); + _UnlockNote(); } // Runtime hook wrappers -//**************************************************************************/ -/*! - @brief Variable used to determine the runtime logging level -*/ -/**************************************************************************/ -#ifndef NOTE_NODEBUG -int noteLogLevel = NOTE_C_LOG_LEVEL; -#endif - //**************************************************************************/ /*! @brief Set the log level for the _DebugWithLevel function. @@ -699,12 +758,14 @@ void NoteGetFnDebugOutput(debugOutputFn *fn) */ void NoteGetFnTransaction(txnStartFn *startFn, txnStopFn *stopFn) { + _LockNote(); if (startFn != NULL) { *startFn = hookTransactionStart; } if (stopFn != NULL) { *stopFn = hookTransactionStop; } + _UnlockNote(); } /*! @@ -771,6 +832,7 @@ void NoteGetFnNoteMutex(mutexFn *lockFn, mutexFn *unlockFn) void NoteGetFn(mallocFn *mallocHook, freeFn *freeHook, delayMsFn *delayMsHook, getMsFn *getMsHook) { + _LockNote(); if (mallocHook != NULL) { *mallocHook = hookMalloc; } @@ -783,6 +845,7 @@ void NoteGetFn(mallocFn *mallocHook, freeFn *freeHook, delayMsFn *delayMsHook, if (getMsHook != NULL) { *getMsHook = hookGetMs; } + _UnlockNote(); } /*! @@ -795,6 +858,7 @@ void NoteGetFn(mallocFn *mallocHook, freeFn *freeHook, delayMsFn *delayMsHook, void NoteGetFnSerial(serialResetFn *resetFn, serialTransmitFn *transmitFn, serialAvailableFn *availFn, serialReceiveFn *receiveFn) { + _LockNote(); if (resetFn != NULL) { *resetFn = hookSerialReset; } @@ -807,6 +871,7 @@ void NoteGetFnSerial(serialResetFn *resetFn, serialTransmitFn *transmitFn, if (receiveFn != NULL) { *receiveFn = hookSerialReceive; } + _UnlockNote(); } /*! @@ -821,6 +886,7 @@ void NoteGetFnI2C(uint32_t *notecardAddr, uint32_t *maxTransmitSize, i2cResetFn *resetFn, i2cTransmitFn *transmitFn, i2cReceiveFn *receiveFn) { + _LockNote(); if (notecardAddr != NULL) { *notecardAddr = i2cAddress; } @@ -836,34 +902,18 @@ void NoteGetFnI2C(uint32_t *notecardAddr, uint32_t *maxTransmitSize, if (receiveFn != NULL) { *receiveFn = hookI2CReceive; } + _UnlockNote(); } /*! @brief Get the I2C address of the Notecard. - @param i2caddress Pointer to store the I2C address. -*/ -void NoteGetI2CAddress(uint32_t *i2caddress) -{ - if (i2caddress != NULL) { - *i2caddress = i2cAddress; - } -} - -//**************************************************************************/ -/*! - @brief Get the active interface's name - @returns A string + @param i2cAddr Pointer to store the I2C address. */ -/**************************************************************************/ -const char *_noteActiveInterface(void) +void NoteGetI2CAddress(uint32_t *i2cAddr) { - switch (hookActiveInterface) { - case interfaceSerial: - return "serial"; - case interfaceI2C: - return "i2c"; + if (i2cAddr != NULL) { + *i2cAddr = i2cAddress; } - return "unknown"; } //**************************************************************************/ @@ -874,7 +924,7 @@ const char *_noteActiveInterface(void) /**************************************************************************/ bool _noteSerialReset(void) { - if (hookActiveInterface == interfaceSerial && hookSerialReset != NULL) { + if (hookActiveInterface == NOTE_C_INTERFACE_SERIAL && hookSerialReset != NULL) { return hookSerialReset(); } return true; @@ -890,7 +940,7 @@ bool _noteSerialReset(void) /**************************************************************************/ void _noteSerialTransmit(uint8_t *text, size_t len, bool flush) { - if (hookActiveInterface == interfaceSerial && hookSerialTransmit != NULL) { + if (hookActiveInterface == NOTE_C_INTERFACE_SERIAL && hookSerialTransmit != NULL) { hookSerialTransmit(text, len, flush); } } @@ -904,7 +954,7 @@ void _noteSerialTransmit(uint8_t *text, size_t len, bool flush) /**************************************************************************/ bool _noteSerialAvailable(void) { - if (hookActiveInterface == interfaceSerial && hookSerialAvailable != NULL) { + if (hookActiveInterface == NOTE_C_INTERFACE_SERIAL && hookSerialAvailable != NULL) { return hookSerialAvailable(); } return false; @@ -919,10 +969,10 @@ bool _noteSerialAvailable(void) /**************************************************************************/ char _noteSerialReceive(void) { - if (hookActiveInterface == interfaceSerial && hookSerialReceive != NULL) { + if (hookActiveInterface == NOTE_C_INTERFACE_SERIAL && hookSerialReceive != NULL) { return hookSerialReceive(); } - return 0; + return '\0'; } //**************************************************************************/ @@ -933,7 +983,7 @@ char _noteSerialReceive(void) /**************************************************************************/ bool _noteI2CReset(uint16_t DevAddress) { - if (hookActiveInterface == interfaceI2C && hookI2CReset != NULL) { + if (hookActiveInterface == NOTE_C_INTERFACE_I2C && hookI2CReset != NULL) { return hookI2CReset(DevAddress); } return true; @@ -951,7 +1001,7 @@ bool _noteI2CReset(uint16_t DevAddress) /**************************************************************************/ const char *_noteI2CTransmit(uint16_t DevAddress, uint8_t* pBuffer, uint16_t Size) { - if (hookActiveInterface == interfaceI2C && hookI2CTransmit != NULL) { + if (hookActiveInterface == NOTE_C_INTERFACE_I2C && hookI2CTransmit != NULL) { return hookI2CTransmit(DevAddress, pBuffer, Size); } return "i2c not active"; @@ -970,7 +1020,7 @@ const char *_noteI2CTransmit(uint16_t DevAddress, uint8_t* pBuffer, uint16_t Siz /**************************************************************************/ const char *_noteI2CReceive(uint16_t DevAddress, uint8_t* pBuffer, uint16_t Size, uint32_t *available) { - if (hookActiveInterface == interfaceI2C && hookI2CReceive != NULL) { + if (hookActiveInterface == NOTE_C_INTERFACE_I2C && hookI2CReceive != NULL) { return hookI2CReceive(DevAddress, pBuffer, Size, available); } return "i2c not active"; @@ -993,12 +1043,12 @@ uint32_t NoteI2CAddress(void) //**************************************************************************/ /*! @brief Set the I2C address for communication with the Notecard. - @param i2caddress the I2C address to use for the Notecard. + @param i2cAddr the I2C address to use for the Notecard. */ /**************************************************************************/ -void NoteSetI2CAddress(uint32_t i2caddress) +void NoteSetI2CAddress(uint32_t i2cAddr) { - i2cAddress = i2caddress; + i2cAddress = i2cAddr; } //**************************************************************************/ @@ -1022,7 +1072,6 @@ uint32_t NoteI2CMax(void) return i2cMax; } - //**************************************************************************/ /*! @brief Perform a hard reset on the Notecard using the platform-specific @@ -1059,8 +1108,8 @@ bool _noteHardReset(void) /**************************************************************************/ const char *_noteJSONTransaction(const char *request, size_t reqLen, char **response, uint32_t timeoutMs) { - if (notecardTransaction == NULL || hookActiveInterface == interfaceNone) { - return "i2c or serial interface must be selected"; + if (notecardTransaction == NULL || hookActiveInterface == NOTE_C_INTERFACE_NONE) { + return "a valid interface must be selected"; } return notecardTransaction(request, reqLen, response, timeoutMs); } @@ -1086,8 +1135,8 @@ const char *_noteJSONTransaction(const char *request, size_t reqLen, char **resp const char *_noteChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, uint32_t timeoutMs, uint32_t *available) { - if (notecardChunkedReceive == NULL || hookActiveInterface == interfaceNone) { - return "i2c or serial interface must be selected"; + if (notecardChunkedReceive == NULL || hookActiveInterface == NOTE_C_INTERFACE_NONE) { + return "a valid interface must be selected"; } return notecardChunkedReceive(buffer, size, delay, timeoutMs, available); } @@ -1104,8 +1153,8 @@ const char *_noteChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, /**************************************************************************/ const char *_noteChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay) { - if (notecardChunkedTransmit == NULL || hookActiveInterface == interfaceNone) { - return "i2c or serial interface must be selected"; + if (notecardChunkedTransmit == NULL || hookActiveInterface == NOTE_C_INTERFACE_NONE) { + return "a valid interface must be selected"; } return notecardChunkedTransmit(buffer, size, delay); } diff --git a/src/note-c/n_i2c.c b/src/note-c/n_i2c.c index 28d5733..fbfdffe 100644 --- a/src/note-c/n_i2c.c +++ b/src/note-c/n_i2c.c @@ -311,6 +311,33 @@ bool _i2cNoteReset(void) return notecardReady; } +/**************************************************************************/ +/*! + @brief Receive bytes over I2C from the Notecard. + + @param buffer A buffer to receive bytes into. + @param size (in/out) + - (in) The size of the buffer in bytes. + - (out) The length of the received data in bytes. + @param delay Respect standard processing delays. + @param timeoutMs The maximum amount of time, in milliseconds, to wait for + serial data to arrive. Passing zero (0) disables the timeout. + @param available (in/out) + - (in) The amount of bytes to request. Sending zero (0) will + initiate a priming query when using the I2C interface. + - (out) The amount of bytes unable to fit into the provided buffer. + + @returns A c-string with an error, or `NULL` if no error ocurred. +*/ +/**************************************************************************/ +const char *_i2cNoteChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, uint32_t timeoutMs, uint32_t *available) +{ + _LockI2C(); + const char *errstr = _i2cChunkedReceive(buffer, size, delay, timeoutMs, available); + _UnlockI2C(); + return errstr; +} + /**************************************************************************/ /*! @brief Receive bytes over I2C from the Notecard. @@ -410,6 +437,25 @@ const char *_i2cChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, uint return NULL; } +/**************************************************************************/ +/*! + @brief Transmit bytes over I2C to the Notecard. + + @param buffer A buffer of bytes to transmit. + @param size The count of bytes in the buffer to send + @param delay Respect standard processing delays. + + @returns A c-string with an error, or `NULL` if no error ocurred. +*/ +/**************************************************************************/ +const char *_i2cNoteChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay) +{ + _LockI2C(); + const char *errstr = _i2cChunkedTransmit(buffer, size, delay); + _UnlockI2C(); + return errstr; +} + /**************************************************************************/ /*! @brief Transmit bytes over I2C to the Notecard. @@ -435,7 +481,9 @@ const char *_i2cChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay) // Constrain chunkLen to be <= _I2CMax(). chunkLen = (chunkLen > _I2CMax()) ? _I2CMax() : chunkLen; - _delayIO(); + if (delay) { + _delayIO(); + } estr = _I2CTransmit(_I2CAddress(), chunk, chunkLen); if (estr != NULL) { _I2CReset(_I2CAddress()); diff --git a/src/note-c/n_lib.h b/src/note-c/n_lib.h index d528309..c8e531b 100644 --- a/src/note-c/n_lib.h +++ b/src/note-c/n_lib.h @@ -29,6 +29,7 @@ extern "C" { */ /**************************************************************************/ #ifdef NOTE_C_TEST +#include "test/include/test_static.h" #define NOTE_C_STATIC #else #define NOTE_C_STATIC static @@ -125,6 +126,8 @@ const char *_serialNoteTransaction(const char *request, size_t reqLen, char **re bool _serialNoteReset(void); const char *_i2cChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, uint32_t timeoutMs, uint32_t *available); const char *_i2cChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay); +const char *_i2cNoteChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, uint32_t timeoutMs, uint32_t *available); +const char *_i2cNoteChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay); const char *_serialChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, uint32_t timeoutMs, uint32_t *available); const char *_serialChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay); diff --git a/src/note-c/n_printf.c b/src/note-c/n_printf.c index 2cbdc69..b7a73dd 100644 --- a/src/note-c/n_printf.c +++ b/src/note-c/n_printf.c @@ -11,9 +11,10 @@ * */ -#include -#include #include +#include +#include + #include "n_lib.h" // Externalized Hooks diff --git a/src/note-c/n_request.c b/src/note-c/n_request.c index 16b1531..cc39906 100644 --- a/src/note-c/n_request.c +++ b/src/note-c/n_request.c @@ -663,16 +663,14 @@ J *_noteTransactionShouldLock(J *req, bool lockNotecard) if (rsp != NULL) { NOTE_C_LOG_ERROR(JGetString(rsp, c_err)); } - if (responseJSON != NULL) { - JFree(responseJSON); - responseJSON = NULL; - } - if (isBadBin) { - errStr = ERRSTR("notecard binary i/o error {bad-bin}{io}", c_badbinerr); NOTE_C_LOG_DEBUG("{bad-bin} is not elibigle for retry"); break; } else { + if (responseJSON != NULL) { + JFree(responseJSON); + responseJSON = NULL; + } errStr = ERRSTR("notecard i/o error {io}", c_ioerr); lastRequestRetries++; NOTE_C_LOG_WARN(ERRSTR("retrying I/O error detected by notecard", c_iobad)); diff --git a/src/note-c/n_ua.c b/src/note-c/n_ua.c index f38b00b..8e5def8 100644 --- a/src/note-c/n_ua.c +++ b/src/note-c/n_ua.c @@ -129,7 +129,21 @@ __attribute__((weak)) J *NoteUserAgent() JAddStringToObject(ua, "agent", n_agent); JAddStringToObject(ua, "compiler", compiler); - JAddStringToObject(ua, "req_interface", _noteActiveInterface()); + + switch (NoteGetActiveInterface()) { + case NOTE_C_INTERFACE_NONE: + JAddStringToObject(ua, "req_interface", "none"); + break; + case NOTE_C_INTERFACE_SERIAL: + JAddStringToObject(ua, "req_interface", "serial"); + break; + case NOTE_C_INTERFACE_I2C: + JAddStringToObject(ua, "req_interface", "i2c"); + break; + default: + JAddStringToObject(ua, "req_interface", "unknown"); + break; + } // Add CPU Details if (n_cpu_cores != 0) { diff --git a/src/note-c/note.h b/src/note-c/note.h index b2dbecf..32d4cfb 100644 --- a/src/note-c/note.h +++ b/src/note-c/note.h @@ -30,11 +30,17 @@ #include #include +enum { + NOTE_C_INTERFACE_NONE = 0, + NOTE_C_INTERFACE_SERIAL, + NOTE_C_INTERFACE_I2C, +}; + #define _NOTE_C_STRINGIZE(x) #x #define NOTE_C_STRINGIZE(x) _NOTE_C_STRINGIZE(x) #define NOTE_C_VERSION_MAJOR 2 -#define NOTE_C_VERSION_MINOR 3 +#define NOTE_C_VERSION_MINOR 4 #define NOTE_C_VERSION_PATCH 1 #define NOTE_C_VERSION NOTE_C_STRINGIZE(NOTE_C_VERSION_MAJOR) "." NOTE_C_STRINGIZE(NOTE_C_VERSION_MINOR) "." NOTE_C_STRINGIZE(NOTE_C_VERSION_PATCH) @@ -298,9 +304,11 @@ void NoteSetFnI2C(uint32_t notecardAddr, uint32_t maxTransmitSize, void NoteGetFnI2C(uint32_t *notecardAddr, uint32_t *maxTransmitSize, i2cResetFn *resetFn, i2cTransmitFn *transmitFn, i2cReceiveFn *receiveFn); +void NoteSetActiveInterface(int interface); +int NoteGetActiveInterface(void); void NoteSetFnDisabled(void); -void NoteSetI2CAddress(uint32_t i2caddress); -void NoteGetI2CAddress(uint32_t *i2caddress); +void NoteSetI2CAddress(uint32_t i2cAddr); +void NoteGetI2CAddress(uint32_t *i2cAddr); // The Notecard, whose default I2C address is below, uses a serial-to-i2c // protocol whose "byte count" must fit into a single byte and which must not @@ -395,12 +403,17 @@ void NoteDebugWithLevelLn(uint8_t level, const char *msg); NoteDebugWithLevelLn(NOTE_C_LOG_LEVEL_DEBUG, msg); \ } while (0); +// The default log level +#define NOTE_C_LOG_LEVEL_DEFAULT NOTE_C_LOG_LEVEL_INFO + // The max log level for NoteDebugWithLevel may be configured at -// compile-time, via NOTE_C_LOG_LEVEL. +// compile-time, via NOTE_C_LOG_LEVEL, otherwise it defaults to +// NOTE_C_LOG_LEVEL_DEFAULT. #ifndef NOTE_C_LOG_LEVEL -#define NOTE_C_LOG_LEVEL NOTE_C_LOG_LEVEL_INFO +#define NOTE_C_LOG_LEVEL NOTE_C_LOG_LEVEL_DEFAULT #endif -// Otherwise, it may be set at runtime, via NoteSetLogLevel. + +// Log level may also be set at runtime, via NoteSetLogLevel. void NoteSetLogLevel(int level); void *NoteMalloc(size_t size);