Skip to content

Commit

Permalink
feat: I2C and Notecard mutex callbacks (#100)
Browse files Browse the repository at this point in the history
* feat: I2C and Notecard mutex callbacks

* appease the comment warrior
  • Loading branch information
zfields authored Apr 4, 2023
1 parent 9d29a7b commit 1d3c537
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 109 deletions.
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ responseError KEYWORD2
sendRequest KEYWORD2
sendRequestWithRetry KEYWORD2
setDebugOutputStream KEYWORD2
setFnI2cMutex KEYWORD2
setFnNoteMutex KEYWORD2
setTransactionPins KEYWORD2

########################################
Expand Down
251 changes: 142 additions & 109 deletions src/Notecard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,75 +252,72 @@ void Notecard::begin(NoteSerial * noteSerial_)

/**************************************************************************/
/*!
@brief Set the debug output source.
A NoteLog object will be constructed via `make_note_log()`
using a platform specific logging channel (for example, `Serial`
on Arduino). The specified channel will be configured as the
source for debug messages provided to `notecard.logDebug()`.
@param noteLog
A platform specific log implementation to be used for
debug output.
@brief Clear the debug output source.
*/
/**************************************************************************/
void Notecard::setDebugOutputStream(NoteLog * noteLog_)
void Notecard::clearDebugOutputStream(void)
{
noteLog = noteLog_;
if (noteLog) {
NoteSetFnDebugOutput(noteLogPrint);
} else {
NoteSetFnDebugOutput(nullptr);
}
noteLog = nullptr;
NoteSetFnDebugOutput(nullptr);
}

/**************************************************************************/
/*!
@brief Clear the debug output source.
@brief Periodically show Notecard sync status, returning `TRUE`
if something was displayed to the debug stream.
@param pollFrequencyMs
The frequency to poll the Notecard for sync status.
@param maxLevel
The maximum log level to output to the debug console. Pass
-1 for all.
@return `True` if a pending response was displayed to the debug stream.
*/
/**************************************************************************/
void Notecard::clearDebugOutputStream(void)
bool Notecard::debugSyncStatus(int pollFrequencyMs, int maxLevel)
{
noteLog = nullptr;
NoteSetFnDebugOutput(nullptr);
return NoteDebugSyncStatus(pollFrequencyMs, maxLevel);
}

/**************************************************************************/
/*!
@brief Set the transaction pins.
A NoteTxn object will be constructed via `make_note_txn()`
using a platform specific tuple of digital I/O pins. The
pins are used to send a request to transact and a listen
for the clear to transact signal. Transaction pins are not
necessary on any legacy Notecards, and are only necessary
for certain Notecard SKUs. The pins allow the Notecard to
inform the host it has had time to awaken from deep sleep
and is ready to process commands.
@param noteTxn
A platform specific tuple of digital I/O pins.
@brief Deletes a `J` JSON response object from memory.
@param rsp
A `J` JSON response object.
*/
/**************************************************************************/
void Notecard::setTransactionPins(NoteTxn * noteTxn_) {
noteTxn = noteTxn_; // Set global interface
if (noteTxn_) {
NoteSetFnTransaction(noteTransactionStart, noteTransactionStop);
} else {
make_note_txn(nullptr); // Clear singleton
NoteSetFnTransaction(nullptr, nullptr);
}
void Notecard::deleteResponse(J *rsp)
{
NoteDeleteResponse(rsp);
}

/**************************************************************************/
/*!
@brief Creates a new request object for population by the host.
This function accepts a request string (for example, `"note.add"`)
and initializes a JSON Object to return to the host.
@param request
The request name, for example, `note.add`.
@return A `J` JSON Object populated with the request name.
@brief Write a message to the serial debug stream.
@param message
A string to log to the serial debug stream.
*/
/**************************************************************************/
J *Notecard::newRequest(const char *request)
void Notecard::logDebug(const char *message)
{
return NoteNewRequest(request);
NoteDebug(message);
}

/**************************************************************************/
/*!
@brief Write a formatted message to the serial debug stream.
@param format
A format string to log to the serial debug stream.
@param ... one or more values to interpolate into the format string.
*/
/**************************************************************************/
void Notecard::logDebugf(const char *format, ...)
{
char message[256];
va_list args;
va_start(args, format);
vsnprintf(message, sizeof(message), format, args);
va_end(args);
NoteDebug(message);
}

/**************************************************************************/
Expand All @@ -340,35 +337,17 @@ J *Notecard::newCommand(const char *request)

/**************************************************************************/
/*!
@brief Sends a request to the Notecard.
This function takes a populated `J` JSON request object
and sends it to the Notecard.
@param req
A `J` JSON request object.
@return `True` if the message was successfully sent to the Notecard,
`False` if there was an error.
*/
/**************************************************************************/
bool Notecard::sendRequest(J *req)
{
return NoteRequest(req);
}

/**************************************************************************/
/*!
@brief Sends a request to the Notecard, retrying it on failure until the
provided timeout interval lapses.
@param req
A `J` JSON request object.
@param timeoutSeconds
The timeout interval, in seconds.
@return `True` if the message was successfully sent to the Notecard,
`False` if the message couldn't be sent.
@brief Creates a new request object for population by the host.
This function accepts a request string (for example, `"note.add"`)
and initializes a JSON Object to return to the host.
@param request
The request name, for example, `note.add`.
@return A `J` JSON Object populated with the request name.
*/
/**************************************************************************/
bool Notecard::sendRequestWithRetry(J *req, uint32_t timeoutSeconds)
J *Notecard::newRequest(const char *request)
{
return NoteRequestWithRetry(req, timeoutSeconds);
return NoteNewRequest(request);
}

/**************************************************************************/
Expand Down Expand Up @@ -404,72 +383,126 @@ J *Notecard::requestAndResponseWithRetry(J *req, uint32_t timeoutSeconds)

/**************************************************************************/
/*!
@brief Deletes a `J` JSON response object from memory.
@brief Determines if there is an error string present in a response object.
@param rsp
A `J` JSON response object.
A `J` JSON Response object.
@return `true` if the response object contains an error.
*/
/**************************************************************************/
void Notecard::deleteResponse(J *rsp)
bool Notecard::responseError(J *rsp)
{
NoteDeleteResponse(rsp);
return NoteResponseError(rsp);
}

/**************************************************************************/
/*!
@brief Write a message to the serial debug stream.
@param message
A string to log to the serial debug stream.
@brief Sends a request to the Notecard.
This function takes a populated `J` JSON request object
and sends it to the Notecard.
@param req
A `J` JSON request object.
@return `True` if the message was successfully sent to the Notecard,
`False` if there was an error.
*/
/**************************************************************************/
void Notecard::logDebug(const char *message)
bool Notecard::sendRequest(J *req)
{
NoteDebug(message);
return NoteRequest(req);
}

/**************************************************************************/
/*!
@brief Write a formatted message to the serial debug stream.
@param format
A format string to log to the serial debug stream.
@param ... one or more values to interpolate into the format string.
@brief Sends a request to the Notecard, retrying it on failure until the
provided timeout interval lapses.
@param req
A `J` JSON request object.
@param timeoutSeconds
The timeout interval, in seconds.
@return `True` if the message was successfully sent to the Notecard,
`False` if the message couldn't be sent.
*/
/**************************************************************************/
void Notecard::logDebugf(const char *format, ...)
bool Notecard::sendRequestWithRetry(J *req, uint32_t timeoutSeconds)
{
char message[256];
va_list args;
va_start(args, format);
vsnprintf(message, sizeof(message), format, args);
va_end(args);
NoteDebug(message);
return NoteRequestWithRetry(req, timeoutSeconds);
}

/**************************************************************************/
/*!
@brief Periodically show Notecard sync status, returning `TRUE`
if something was displayed to the debug stream.
@param pollFrequencyMs
The frequency to poll the Notecard for sync status.
@param maxLevel
The maximum log level to output to the debug console. Pass
-1 for all.
@return `True` if a pending response was displayed to the debug stream.
@brief Set the debug output source.
A NoteLog object will be constructed via `make_note_log()`
using a platform specific logging channel (for example, `Serial`
on Arduino). The specified channel will be configured as the
source for debug messages provided to `notecard.logDebug()`.
@param noteLog
A platform specific log implementation to be used for
debug output.
*/
/**************************************************************************/
bool Notecard::debugSyncStatus(int pollFrequencyMs, int maxLevel)
void Notecard::setDebugOutputStream(NoteLog * noteLog_)
{
return NoteDebugSyncStatus(pollFrequencyMs, maxLevel);
noteLog = noteLog_;
if (noteLog) {
NoteSetFnDebugOutput(noteLogPrint);
} else {
NoteSetFnDebugOutput(nullptr);
}
}

/**************************************************************************/
/*!
@brief Determines if there is an error string present in a response object.
@param rsp
A `J` JSON Response object.
@return `True` if the response object contains an error.
@brief Set the lock/unlock functions the Notecard uses for I2C access.
@param lockI2cFn
A user-defined callback that blocks until access to the I2C
bus has become available, then returns with ownership of the
I2C bus.
@param unlockI2cFn
A user-defined callback that releases ownership of the
I2C bus taken during the call to `lockI2cFn()`.
*/
/**************************************************************************/
bool Notecard::responseError(J *rsp)
{
return NoteResponseError(rsp);
void Notecard::setFnI2cMutex(mutexFn lockI2cFn_, mutexFn unlockI2cFn_) {
NoteSetFnI2CMutex(lockI2cFn_, unlockI2cFn_);
}

/**************************************************************************/
/*!
@brief Set the lock/unlock functions the host MCU uses to ensure
a complete transaction with the Notecard.
@param lockNoteFn
A user-defined callback that blocks until the Notecard has
completed any previous transactions, then returns with
ownership of the next Notecard transaction.
@param unlockNoteFn
A user-defined callback that releases ownership of the
Notecard transaction taken during the call to `lockNoteFn()`.
*/
/**************************************************************************/
void Notecard::setFnNoteMutex(mutexFn lockNoteFn_, mutexFn unlockNoteFn_) {
NoteSetFnNoteMutex(lockNoteFn_, unlockNoteFn_);
}

/**************************************************************************/
/*!
@brief Set the transaction pins.
A NoteTxn object will be constructed via `make_note_txn()`
using a platform specific tuple of digital I/O pins. The
pins are used to send a request to transact and to listen
for the clear to transact signal. Transaction pins are not
necessary on any legacy Notecards, and are only necessary
for certain Notecard SKUs. The pins allow the Notecard to
inform the host it has had time to awaken from deep sleep
and is ready to process commands.
@param noteTxn
A platform specific tuple of digital I/O pins.
*/
/**************************************************************************/
void Notecard::setTransactionPins(NoteTxn * noteTxn_) {
noteTxn = noteTxn_; // Set global interface
if (noteTxn_) {
NoteSetFnTransaction(noteTransactionStart, noteTransactionStop);
} else {
make_note_txn(nullptr); // Clear singleton
NoteSetFnTransaction(nullptr, nullptr);
}
}
2 changes: 2 additions & 0 deletions src/Notecard.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class Notecard
bool sendRequest(J *req);
bool sendRequestWithRetry(J *req, uint32_t timeoutSeconds);
void setDebugOutputStream(NoteLog * noteLog);
void setFnI2cMutex(mutexFn lockI2cFn, mutexFn unlockI2cFn);
void setFnNoteMutex(mutexFn lockNoteFn, mutexFn unlockNoteFn);
void setTransactionPins(NoteTxn * noteTxn);

private:
Expand Down
Loading

0 comments on commit 1d3c537

Please sign in to comment.