Host software for the MAX30001 ECG, PACE, biopotential, bioimpedance, R-to-R peak sensor. Hosted on the MAX32630FTHR.
Dependencies: SDFileSystem USBDevice max32630fthr
Fork of MAX30001-MAX32630FTHR-ECG-EVKIT by
Diff: HSP/RpcServer/RpcServer.cpp
- Revision:
- 0:8e4630a71eb1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HSP/RpcServer/RpcServer.cpp Thu Apr 05 10:53:26 2018 +0300 @@ -0,0 +1,399 @@ +/******************************************************************************* + * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Maxim Integrated + * Products, Inc. shall not be used except as stated in the Maxim Integrated + * Products, Inc. Branding Policy. + * + * The mere transfer of this software does not imply any licenses + * of trade secrets, proprietary technology, copyrights, patents, + * trademarks, maskwork rights, or any other form of intellectual + * property whatsoever. Maxim Integrated Products, Inc. retains all + * ownership rights. + ******************************************************************************* + */ +#include "RpcServer.h" +#include "StringInOut.h" +#include "StringHelper.h" +#include "MAX30001_RPC.h" +#include "Logging_RPC.h" +#include "Peripherals.h" +#include "HspLed_RPC.h" +#include "S25FS512_RPC.h" +#include "Testing_RPC.h" +#include "RpcDeclarations.h" +#include "Device_Logging.h" +#include "../version.h" + +/// define the version string that is reported with a RPC "ReadVer" command +#define FW_VERSION_STRING "MAX30001 FW Ver" + +char args[32][32]; +char results[32][32]; + +/// define a fifo for incoming USB data +static fifo_t fifo; +/// define a buffer for incoming USB data +static uint8_t fifoBuffer[128]; +/// define stream out fifo +static fifo_t fifoStreamOut; +/// allocate a large fifo buffer for streaming out +static uint32_t streamOutBuffer[0xC000 / 4]; + +/// define a device log for the BMP280, keeps track of mission and loggin status +Device_Logging *bmp280_Logging; +/// define a device log for the MAX30205 (instance 0), keeps track of mission +/// and loggin status +Device_Logging *MAX30205_0_Logging; +/// define a device log for the MAX30205 (instance 1), keeps track of mission +/// and loggin status +Device_Logging *MAX30205_1_Logging; + +//****************************************************************************** +fifo_t *GetUSBIncomingFifo(void) { return &fifo; } + +//****************************************************************************** +fifo_t *GetStreamOutFifo(void) { return &fifoStreamOut; } + +//****************************************************************************** +int System_ReadVer(char argStrs[32][32], char replyStrs[32][32]) { + char version[32]; + snprintf(version, sizeof(version)/sizeof(char), "%s %d.%d.%d %02d/%02d/%02d", + FW_VERSION_STRING, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, + VERSION_MONTH, VERSION_DAY, VERSION_SHORT_YEAR); + strcpy(replyStrs[0], version); + strcpy(replyStrs[1], "\0"); + return 0; +} + +//****************************************************************************** +int System_ReadBuildTime(char argStrs[32][32], char replyStrs[32][32]) { + // strcpy(replyStrs[0],buildTime); + // strcpy(replyStrs[1],"\0"); + return 0; +} + +//****************************************************************************** +int System_SystemCoreClock(char argStrs[32][32], char replyStrs[32][32]) { + sprintf(replyStrs[0], "SystemCoreClock = %d", SystemCoreClock); + strcpy(replyStrs[1], "\0"); + return 0; +} + +//****************************************************************************** +int System_GetTimestamp(char argStrs[32][32], char replyStrs[32][32]) { + sprintf(replyStrs[0], "GetTimestamp = %d", 0); + strcpy(replyStrs[1], "\0"); + return 0; +} + +static struct RPC_Object RPC_Procedures = {NULL, NULL}; + +//****************************************************************************** +void RPC_addProcedure(struct RPC_registeredProcedure *procedure) { + struct RPC_Object *obj = &RPC_Procedures; + if (obj->last != NULL) { + obj->last->next = procedure; + } + if (obj->head == NULL) { + obj->head = procedure; + } + procedure->next = NULL; + obj->last = procedure; +} + +//****************************************************************************** +void RPC_init(void) { + + fifo_init(&fifo, fifoBuffer, sizeof(fifoBuffer)); + fifo_init(&fifoStreamOut, streamOutBuffer, + sizeof(streamOutBuffer) / sizeof(uint32_t)); + + // MAX30001 + RPC_addProcedure(&Define_MAX30001_WriteReg); + RPC_addProcedure(&Define_MAX30001_ReadReg); + RPC_addProcedure(&Define_MAX30001_Start); + RPC_addProcedure(&Define_MAX30001_Stop); + RPC_addProcedure(&Define_MAX30001_Enable_ECG_LeadON); + RPC_addProcedure(&Define_MAX30001_Enable_BIOZ_LeadON); + RPC_addProcedure(&Define_MAX30001_Read_LeadON); + RPC_addProcedure(&Define_MAX30001_StartTest); + RPC_addProcedure(&Define_MAX30001_INT_assignment); + RPC_addProcedure(&Define_MAX30001_Rbias_FMSTR_Init); + RPC_addProcedure(&Define_MAX30001_CAL_InitStart); + RPC_addProcedure(&Define_MAX30001_ECG_InitStart); + RPC_addProcedure(&Define_MAX30001_ECGFast_Init); + RPC_addProcedure(&Define_MAX30001_PACE_InitStart); + RPC_addProcedure(&Define_MAX30001_BIOZ_InitStart); + RPC_addProcedure(&Define_MAX30001_RtoR_InitStart); + RPC_addProcedure(&Define_MAX30001_Stop_ECG); + RPC_addProcedure(&Define_MAX30001_Stop_PACE); + RPC_addProcedure(&Define_MAX30001_Stop_BIOZ); + RPC_addProcedure(&Define_MAX30001_Stop_RtoR); + RPC_addProcedure(&Define_MAX30001_Stop_Cal); + + // Logging + RPC_addProcedure(&Define_Logging_StartMissionDefine); + RPC_addProcedure(&Define_Logging_AppendMissionCmd); + RPC_addProcedure(&Define_Logging_EndMissionDefine); + RPC_addProcedure(&Define_Logging_WriteMission); + RPC_addProcedure(&Define_Logging_ReadMission); + RPC_addProcedure(&Define_Logging_EraseMission); + RPC_addProcedure(&Define_Logging_EraseWrittenSectors); + RPC_addProcedure(&Define_Logging_StartLoggingUsb); + RPC_addProcedure(&Define_Logging_StartLoggingFlash); + RPC_addProcedure(&Define_Logging_GetLastWrittenPage); + RPC_addProcedure(&Define_Logging_Start); + + // led + RPC_addProcedure(&Define_Led_On); + RPC_addProcedure(&Define_Led_Off); + RPC_addProcedure(&Define_Led_BlinkHz); + RPC_addProcedure(&Define_Led_BlinkPattern); + + // S25FS512 + RPC_addProcedure(&Define_S25FS512_ReadId); + RPC_addProcedure(&Define_S25FS512_ReadPagesBinary); + RPC_addProcedure(&Define_S25FS512_Reset); + RPC_addProcedure(&Define_S25FS512_EnableHWReset); + RPC_addProcedure(&Define_S25FS512_SpiWriteRead); + RPC_addProcedure(&Define_S25FS512_SpiWriteRead4Wire); + + RPC_addProcedure(&Define_Testing_Test_MAX30001); + + // SDCard + RPC_addProcedure(&Define_SDCard_IsReady); + + // System + RPC_addProcedure(&Define_System_ReadVer); + RPC_addProcedure(&Define_System_ReadBuildTime); +} + +//****************************************************************************** +struct RPC_registeredProcedure *RPC_lookup(char *objectName, char *methodName) { + struct RPC_registeredProcedure *ptr; + // lookup all registered methods + ptr = RPC_Procedures.head; + while (ptr != NULL) { + if (strcmp(ptr->objectName, objectName) == 0 && + strcmp(ptr->methodName, methodName) == 0) { + // we found a match... return with it + return ptr; + } + ptr = ptr->next; + } + return NULL; +} + +//****************************************************************************** +char *GetToken(char *inStr, char *outStr, int start, char ch) { + int i; + int index = 0; + int length = strlen(inStr); + for (i = start; i < length; i++) { + if (inStr[i] != ch) { + outStr[index++] = inStr[i]; + } else { + break; + } + } + outStr[index++] = 0; + return outStr; +} + +//****************************************************************************** +void SendCommandList(char *reply) { + struct RPC_registeredProcedure *ptr; + reply[0] = 0; + ptr = RPC_Procedures.head; + while (ptr != NULL) { + strcat(reply, "/"); + strcat(reply, ptr->objectName); + strcat(reply, "/"); + strcat(reply, ptr->methodName); + strcat(reply, ","); + ptr = ptr->next; + } + strcat(reply, "\r\n"); +} + +//****************************************************************************** +int CheckForDoubleQuote(char *str) { + int doubleQuoteFound; + // scan through arguments, see if there is a double quote for a string + // argument + doubleQuoteFound = 0; + while (*str != 0) { + if (*str == '\"') { + doubleQuoteFound = 1; + break; + } + str++; + } + return doubleQuoteFound; +} + +//****************************************************************************** +void ExtractDoubleQuoteStr(char *src, char *dst) { + int start; + + dst[0] = 0; + start = 0; + while (*src != 0) { + // look for start + if ((*src == '\"') && (start == 0)) { + start = 1; + src++; + continue; + } + // look for end + if ((*src == '\"') && (start == 1)) { + *dst = 0; // terminate the string + break; + } + if (start == 1) { + *dst = *src; + dst++; + } + src++; + } +} + +//****************************************************************************** +void RPC_call_test(void) { + int doubleQuoteFound; + char doubleQuoteStr[64]; + char *request = "/Logging/AppendMissionCmd \"BMP280 InitStart 1\""; + + // scan through arguments, see if there is a double quote for a string + // argument + doubleQuoteFound = CheckForDoubleQuote(request); + if (doubleQuoteFound) { + ExtractDoubleQuoteStr(request, doubleQuoteStr); + } +} + +//****************************************************************************** +void RPC_call(char *request, char *reply) { + const char slash[2] = "/"; + const char space[2] = " "; + char *objectName; + char *methodName; + char doubleQuoteStr[128]; + char requestCpy[256]; + char *token; + int argIndex; + int resultIndex; + int doubleQuoteFound; + struct RPC_registeredProcedure *procedurePtr; + + // clear out the reply + reply[0] = 0; + // copy the request for scanning and extraction later + strcpy(requestCpy, request); + // check for beginning forward slash + if (request[0] != '/') { + return; + } + // check for only a forward slash + if (request[0] == '/' && request[1] == 0) { + SendCommandList(reply); + return; + } + strcat(request, " "); + // get the object name + token = strtok(request, slash); + // token = GetToken(request, tokenBuffer, 1, '/'); + objectName = token; + if (objectName == NULL) + return; // must have an object name + // get the method name + token = strtok(NULL, space); + methodName = token; + if (methodName == NULL) + return; // must have a method name + + // scan through arguments, see if there is a double quote for a string + // argument + doubleQuoteFound = CheckForDoubleQuote(requestCpy); + + if (doubleQuoteFound == 0) { + // walk through arguments + argIndex = 0; + token = strtok(NULL, space); + while (token != NULL) { + // save this arg in array + strcpy(args[argIndex++], token); + // read next token arg if any + token = strtok(NULL, space); + } + // terminate the end of the string array with an empty string + strcpy(args[argIndex], "\0"); + strcpy(results[0], "\0"); + } else { + // grab out the double quote string + ExtractDoubleQuoteStr(requestCpy, doubleQuoteStr); + argIndex = 0; + // token = strtok(NULL, quote); + strcpy(args[argIndex++], doubleQuoteStr); + } + + // + // alias the MAX30001 and MAX30003 names + // + if (strcmp(objectName, MAX30003_NAME) == 0) { + strcpy(objectName, MAX30001_NAME); + } + + procedurePtr = RPC_lookup(objectName, methodName); + if (procedurePtr != NULL) { + // printf("RPC_call: %s processing\n",requestCpy); + procedurePtr->func(args, results); + } else { + printf("RPC_call: %s not found\n", requestCpy); + // printf("Unable to lookup %s %s", objectName, methodName); + } + + // loop while (if) there are results to return + resultIndex = 0; + strcpy(reply, "\0"); + while (results[resultIndex][0] != '\0') { + strcat(reply, results[resultIndex++]); + strcat(reply, " "); + } + strcat(reply, "\r\n"); +} + +//****************************************************************************** +void RPC_ProcessCmds(char *cmds) { + char cmd[32 * 32]; + char *ptrCmds; + char reply[512]; + ptrCmds = cmds; + + while (*ptrCmds != 0) { + ptrCmds = ParseUntilCRLF(ptrCmds, cmd, sizeof(cmd)); + if (*cmd != 0) { + RPC_call(cmd, reply); + } + } +} +