void paramTOCProcess(int command) { int ptr = 0; char * group = ""; int n=0; switch (command) { case CMD_GET_INFO: //Get info packet about the param implementation ptr = 0; group = ""; p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.size=6; p.data[0]=CMD_GET_INFO; p.data[1]=paramsCount; memcpy(&p.data[2], ¶msCrc, 4); crtpSendPacket(&p); break; case CMD_GET_ITEM: //Get param variable for (ptr=0; ptr<paramsLen; ptr++) //Ptr points a group { if (params[ptr].type & PARAM_GROUP) { if (params[ptr].type & PARAM_START) group = params[ptr].name; else group = ""; } else //Ptr points a variable { if (n==p.data[1]) break; n++; } } if (ptr<paramsLen) { p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.data[0]=CMD_GET_ITEM; p.data[1]=n; p.data[2]=params[ptr].type; memcpy(p.data+3, group, strlen(group)+1); memcpy(p.data+3+strlen(group)+1, params[ptr].name, strlen(params[ptr].name)+1); p.size=3+2+strlen(group)+strlen(params[ptr].name); crtpSendPacket(&p); } else { p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.data[0]=CMD_GET_ITEM; p.size=1; crtpSendPacket(&p); } break; } }
void memSettingsProcess(int command) { uint8_t memId; switch (command) { case CMD_GET_NBR: p.header = CRTP_HEADER(CRTP_PORT_MEM, SETTINGS_CH); p.size = 2; p.data[0] = CMD_GET_NBR; p.data[1] = nbrOwMems + NBR_EEPROM; crtpSendPacket(&p); break; case CMD_GET_INFO: memId = p.data[1]; p.header = CRTP_HEADER(CRTP_PORT_MEM, SETTINGS_CH); p.size = 2; p.data[0] = CMD_GET_INFO; p.data[1] = memId; // No error code if we fail, just send an empty packet back if (memId == EEPROM_ID) { // Memory type (eeprom) p.data[2] = MEM_TYPE_EEPROM; p.size += 1; // Size of the memory memSize = EEPROM_SIZE; memcpy(&p.data[3], &memSize, 4); p.size += 4; memcpy(&p.data[7], eepromSerialNum.data, 8); p.size += 8; } else { if (owGetinfo(memId - NBR_EEPROM, &serialNbr)) { // Memory type (1-wire) p.data[2] = MEM_TYPE_OW; p.size += 1; // Size of the memory TODO: Define length type memSize = OW_MAX_SIZE; memcpy(&p.data[3], &memSize, 4); p.size += 4; memcpy(&p.data[7], serialNbr.data, 8); p.size += 8; } } crtpSendPacket(&p); break; } }
void logControlProcess() { int ret = ENOEXEC; switch (p.data[0]) { case CONTROL_CREATE_BLOCK: ret = logCreateBlock(p.data[1], (struct ops_setting*) &p.data[2], (p.size - 2) / sizeof(struct ops_setting)); break; case CONTROL_APPEND_BLOCK: ret = logAppendBlock(p.data[1], (struct ops_setting*) &p.data[2], (p.size - 2) / sizeof(struct ops_setting)); break; case CONTROL_DELETE_BLOCK: ret = logDeleteBlock(p.data[1]); break; case CONTROL_START_BLOCK: ret = logStartBlock(p.data[1], p.data[2] * 10); break; case CONTROL_STOP_BLOCK: ret = logStopBlock(p.data[1]); break; case CONTROL_RESET: logReset(); ret = 0; break; } //Commands answer p.data[2] = ret; p.size = 3; crtpSendPacket(&p); }
static void versionCommandProcess(CRTPPacket *p) { switch (p->data[0]) { case getProtocolVersion: *(int*)&p->data[1] = PROTOCOL_VERSION; p->size = 5; crtpSendPacket(p); break; case getFirmwareVersion: strncpy((char*)&p->data[1], V_STAG, CRTP_MAX_DATA_SIZE-1); p->size = (strlen(V_STAG)>CRTP_MAX_DATA_SIZE-1)?CRTP_MAX_DATA_SIZE:strlen(V_STAG)+1; crtpSendPacket(p); break; default: break; } }
void memReadProcess() { uint8_t memId = p.data[0]; uint8_t readLen = p.data[5]; uint32_t memAddr; uint8_t status = 0; memcpy(&memAddr, &p.data[1], 4); MEM_DEBUG("Packet is MEM READ\n"); p.header = CRTP_HEADER(CRTP_PORT_MEM, READ_CH); // Dont' touch the first 5 bytes, they will be the same. if (memId == EEPROM_ID) { if (memAddr + readLen <= EEPROM_SIZE && eepromReadBuffer(&p.data[6], memAddr, readLen)) status = 0; else status = EIO; } else if (memId == LEDMEM_ID) { if (memAddr + readLen <= sizeof(ledringmem) && memcpy(&p.data[6], &(ledringmem[memAddr]), readLen)) status = 0; else status = EIO; } else { memId = memId - NBR_STATIC_MEM; if (memAddr + readLen <= OW_MAX_SIZE && owRead(memId, memAddr, readLen, &p.data[6])) status = 0; else status = EIO; } #if 0 { int i; for (i = 0; i < readLen; i++) consolePrintf("%X ", p.data[i+6]); consolePrintf("\nStatus %i\n", status); } #endif p.data[5] = status; if (status == 0) p.size = 6 + readLen; else p.size = 6; crtpSendPacket(&p); }
void crtpserviceHandler(CRTPPacket *p) { switch (p->channel) { case linkEcho: crtpSendPacket(p); break; case linkSource: p->size = CRTP_MAX_DATA_SIZE; crtpSendPacket(p); break; case linkSink: /* Ignore packet */ break; default: break; } }
void memSettingsProcess(int command) { switch (command) { case MEM_CMD_GET_NBR: createNbrResponse(&p); crtpSendPacket(&p); break; } }
void sendSensorData(uint64_t* ts, float* roll, float *pitch, float* yaw, float* acc_x, float* acc_y, float* acc_z, float* gyro_x, float* gyro_y, float* gyro_z) { pk1.header = CRTP_HEADER(CRTP_PORT_SENSORDATA, PACKET1_CH); pk1.size=28; pk1.data[0] = *ts; pk1.data[8] = *roll; pk1.data[12] = *pitch; pk1.data[16] = *yaw; pk1.data[20] = *acc_x; pk1.data[24] = *acc_y; crtpSendPacket(&pk1); pk2.header = CRTP_HEADER(CRTP_PORT_SENSORDATA, PACKET2_CH); pk2.size=24; pk2.data[0] = *ts; pk2.data[8] = *acc_z; pk2.data[12] = *gyro_x; pk2.data[16] = *gyro_y; pk2.data[20] = *gyro_z; crtpSendPacket(&pk2); }
void platformserviceHandler(CRTPPacket *p) { switch (p->channel) { case platformCommand: platformCommandProcess(p->data[0], &p->data[1]); crtpSendPacket(p); break; default: break; } }
static void paramReadProcess(int ident) { int id; id = variableGetIndex(ident); if (id<0) { p.data[0] = -1; p.data[1] = ident; p.data[2] = ENOENT; p.size = 3; crtpSendPacket(&p); return; } switch (params[id].type & PARAM_BYTES_MASK) { case PARAM_1BYTE: memcpy(&p.data[1], params[id].address, sizeof(uint8_t)); p.size = 1+sizeof(uint8_t); break; break; case PARAM_2BYTES: memcpy(&p.data[1], params[id].address, sizeof(uint16_t)); p.size = 1+sizeof(uint16_t); break; case PARAM_4BYTES: memcpy(&p.data[1], params[id].address, sizeof(uint32_t)); p.size = 1+sizeof(uint32_t); break; case PARAM_8BYTES: memcpy(&p.data[1], params[id].address, sizeof(uint64_t)); p.size = 1+sizeof(uint64_t); break; } crtpSendPacket(&p); }
/** * Send the data to the client * returns TRUE if successful otherwise FALSE */ static bool consoleSendMessage(void) { if (crtpSendPacket(&messageToPrint) == pdTRUE) { messageToPrint.size = 0; } else { return false; } return true; }
static void paramWriteProcess(int ident, void* valptr) { int id; id = variableGetIndex(ident); if (id<0) { p.data[0] = -1; p.data[1] = ident; p.data[2] = ENOENT; p.size = 3; crtpSendPacket(&p); return; } if (params[id].type & PARAM_RONLY) return; switch (params[id].type & PARAM_BYTES_MASK) { case PARAM_1BYTE: *(uint8_t*)params[id].address = *(uint8_t*)valptr; break; case PARAM_2BYTES: *(uint16_t*)params[id].address = *(uint16_t*)valptr; break; case PARAM_4BYTES: *(uint32_t*)params[id].address = *(uint32_t*)valptr; break; case PARAM_8BYTES: *(uint64_t*)params[id].address = *(uint64_t*)valptr; break; } crtpSendPacket(&p); }
void paramTask(void * prm) { crtpInitTaskQueue(CRTP_PORT_PARAM); while(1) { crtpReceivePacketBlock(CRTP_PORT_PARAM, &p); if (p.channel==TOC_CH) paramTOCProcess(p.data[0]); else if (p.channel==READ_CH) paramReadProcess(p.data[0]); else if (p.channel==WRITE_CH) paramWriteProcess(p.data[0], &p.data[1]); else if (p.channel==MISC_CH) { if (p.data[0] == MISC_SETBYNAME) { int i, nzero = 0; char *group; char *name; uint8_t type; void * valPtr; int error; // If the packet contains at least 2 zeros in the first 28 bytes // The packet decoding algorithm will not crash for (i=0; i<CRTP_MAX_DATA_SIZE; i++) { if (p.data[i] == '\0') nzero++; } if (nzero < 2) return; group = (char*)&p.data[1]; name = (char*)&p.data[1+strlen(group)+1]; type = p.data[1+strlen(group)+1+strlen(name)+1]; valPtr = &p.data[1+strlen(group)+1+strlen(name)+2]; error = paramWriteByNameProcess(group, name, type, valPtr); p.data[1+strlen(group)+1+strlen(name)+1] = error; p.size = 1+strlen(group)+1+strlen(name)+1+1; crtpSendPacket(&p); } } } }
static void commanderAdvancedCrtpCB(CRTPPacket* pk) { targetVal[!side] = *((struct CommanderAdvancedCrtpValues*) pk->data); side = !side; lastReceived = targetVal[side]; if(targetVal[side].id != 0){ DEBUG_PRINT("\n %d receive a trame from ID %d \n", CRAZYFLIE_ID, targetVal[side].id); } targetVal[side].id = CRAZYFLIE_ID; if (targetVal[side].thrust == 0) { thrustLocked = false; } //TODO //Appliquer des calculs (triangularisation) pour redefinir x, y, z processCommanderAdvanced(); createCommanderAdvancedPacket(pk); crtpSendPacket(pk); commanderAdvancedWatchdogReset(); }
void memWriteProcess() { uint8_t memId = p.data[0]; uint8_t writeLen; uint32_t memAddr; uint8_t status; memcpy(&memAddr, &p.data[1], 4); writeLen = p.size - 5; DEBUG("Packet is MEM WRITE\n"); p.header = CRTP_HEADER(CRTP_PORT_MEM, WRITE_CH); // Dont' touch the first 5 bytes, they will be the same. if (memId == EEPROM_ID) { if (memAddr + writeLen <= EEPROM_SIZE && eepromWriteBuffer(&p.data[5], memAddr, writeLen)) status = 0; else status = EIO; } else { memId = memId - NBR_EEPROM; if (memAddr + writeLen <= OW_MAX_SIZE && owWrite(memId, memAddr, writeLen, &p.data[5])) status = 0; else status = EIO; } p.data[5] = status; p.size = 6; crtpSendPacket(&p); }
/* This function is usually called by the worker subsystem */ void logRunBlock(void * arg) { struct log_block *blk = arg; struct log_ops *ops = blk->ops; static CRTPPacket pk; unsigned int timestamp; xSemaphoreTake(logLock, portMAX_DELAY); timestamp = ((long long)xTaskGetTickCount())/portTICK_RATE_MS; pk.crtp_header = CRTP_HEADER(CRTP_PORT_LOG, LOG_CH); pk.size = 4; pk.crtp_data[0] = blk->id; pk.crtp_data[1] = timestamp&0x0ff; pk.crtp_data[2] = (timestamp>>8)&0x0ff; pk.crtp_data[3] = (timestamp>>16)&0x0ff; while (ops) { int valuei = 0; float valuef = 0; switch(ops->storageType) { case LOG_UINT8: valuei = *(uint8_t *)ops->variable; break; case LOG_INT8: valuei = *(int8_t *)ops->variable; break; case LOG_UINT16: valuei = *(uint16_t *)ops->variable; break; case LOG_INT16: valuei = *(int16_t *)ops->variable; break; case LOG_UINT32: valuei = *(uint32_t *)ops->variable; break; case LOG_INT32: valuei = *(int32_t *)ops->variable; break; case LOG_FLOAT: valuei = *(float *)ops->variable; break; } if (ops->logType == LOG_FLOAT || ops->logType == LOG_FP16) { if (ops->storageType == LOG_FLOAT) valuef = *(float *)ops->variable; else valuef = valuei; if (ops->logType == LOG_FLOAT) { memcpy(&pk.crtp_data[pk.size], &valuef, 4); pk.size += 4; } else { valuei = single2half(valuef); memcpy(&pk.crtp_data[pk.size], &valuei, 2); pk.size += 2; } } else //logType is an integer { memcpy(&pk.crtp_data[pk.size], &valuei, typeLength[ops->logType]); pk.size += typeLength[ops->logType]; } ops = ops->next; } xSemaphoreGive(logLock); // Check if the connection is still up, oherwise disable // all the logging and flush all the CRTP queues. if (!crtpIsConnected()) { logReset(); crtpReset(); } else { crtpSendPacket(&pk); } }
void logTOCProcess(int command) { int ptr = 0; char * group = "plop"; int n=0; switch (command) { case CMD_GET_INFO: //Get info packet about the log implementation DEBUG("Packet is TOC_GET_INFO\n"); ptr = 0; group = ""; p.crtp_header=CRTP_HEADER(CRTP_PORT_LOG, TOC_CH); p.size=8; p.crtp_data[0]=CMD_GET_INFO; p.crtp_data[1]=logsCount; memcpy(&p.crtp_data[2], &logsCrc, 4); p.crtp_data[6]=LOG_MAX_BLOCKS; p.crtp_data[7]=LOG_MAX_OPS; crtpSendPacket(&p); break; case CMD_GET_ITEM: //Get log variable DEBUG("Packet is TOC_GET_ITEM Id: %d\n", p.data[1]); for (ptr=0; ptr<logsLen; ptr++) //Ptr points a group { if (logs[ptr].type & LOG_GROUP) { if (logs[ptr].type & LOG_START) group = logs[ptr].name; else group = ""; } else //Ptr points a variable { if (n==p.crtp_data[1]) break; n++; } } if (ptr<logsLen) { DEBUG(" Item is \"%s\":\"%s\"\n", group, logs[ptr].name); p.crtp_header=CRTP_HEADER(CRTP_PORT_LOG, TOC_CH); p.crtp_data[0]=CMD_GET_ITEM; p.crtp_data[1]=n; p.crtp_data[2]=logs[ptr].type; memcpy(p.crtp_data+3, group, strlen(group)+1); memcpy(p.crtp_data+3+strlen(group)+1, logs[ptr].name, strlen(logs[ptr].name)+1); p.size=3+2+strlen(group)+strlen(logs[ptr].name); crtpSendPacket(&p); } else { DEBUG(" Index out of range!"); p.crtp_header=CRTP_HEADER(CRTP_PORT_LOG, TOC_CH); p.crtp_data[0]=CMD_GET_ITEM; p.size=1; crtpSendPacket(&p); } break; } }
void infoTask(void *param) { CRTPPacket p; int i; static int ctr=0; while (true) { if (crtpReceivePacketWait(crtpInfo, &p, 1000) == pdTRUE) { InfoNbr infoNbr = CRTP_GET_NBR(p.port); switch (infoNbr) { case infoCopterNr: if (p.data[0] == infoName) { p.data[1] = 0x90; p.data[2] = 0x00; //Version 0.9.0 (Crazyflie) strcpy((char*)&p.data[3], "CrazyFlie"); p.size = 3+strlen("CrazyFlie"); crtpSendPacket(&p); } else if (p.data[0] == infoVersion) { i=1; strncpy((char*)&p.data[i], V_SLOCAL_REVISION, 31-i); i += strlen(V_SLOCAL_REVISION); if (i<31) p.data[i++] = ','; strncpy((char*)&p.data[i], V_SREVISION, 31-i); i += strlen(V_SREVISION); if (i<31) p.data[i++] = ','; strncpy((char*)&p.data[i], V_STAG, 31-i); i += strlen(V_STAG); if (i<31) p.data[i++] = ','; if (i<31) p.data[i++] = V_MODIFIED?'M':'C'; p.size = (i<31)?i:31; crtpSendPacket(&p); } else if (p.data[0] == infoCpuId) { memcpy((char*)&p.data[1], (char*)CpuId, 12); p.size = 13; crtpSendPacket(&p); } break; case infoBatteryNr: if (p.data[0] == batteryVoltage) { float value = pmGetBatteryVoltage(); memcpy(&p.data[1], (char*)&value, 4); p.size = 5; crtpSendPacket(&p); } else if (p.data[0] == batteryMax) { float value = pmGetBatteryVoltageMax(); memcpy(&p.data[1], (char*)&value, 4); p.size = 5; crtpSendPacket(&p); } else if (p.data[0] == batteryMin) { float value = pmGetBatteryVoltageMin(); memcpy(&p.data[1], (char*)&value, 4); p.size = 5; crtpSendPacket(&p); } break; default: break; } } // Send a warning message if the battery voltage drops under 3.3V // This is sent every 5 info transaction or every 5 seconds if (ctr++>5) { ctr=0; if (pmGetBatteryVoltageMin() < INFO_BAT_WARNING) { float value = pmGetBatteryVoltage(); p.port = CRTP_PORT(0,8,3); p.data[0] = 0; memcpy(&p.data[1], (char*)&value, 4); p.size = 5; crtpSendPacket(&p); } } } }
/* This function is usually called by the worker subsystem */ void logRunBlock(void * arg) { struct log_block *blk = arg; struct log_ops *ops = blk->ops; static CRTPPacket pk; unsigned int timestamp; xSemaphoreTake(logLock, portMAX_DELAY); timestamp = ((long long)xTaskGetTickCount())/portTICK_RATE_MS; pk.header = CRTP_HEADER(CRTP_PORT_LOG, LOG_CH); pk.size = 4; pk.data[0] = blk->id; pk.data[1] = timestamp&0x0ff; pk.data[2] = (timestamp>>8)&0x0ff; pk.data[3] = (timestamp>>16)&0x0ff; while (ops) { float variable; int valuei = 0; float valuef = 0; // FPU instructions must run on aligned data. Make sure it is. variable = *(float *)ops->variable; switch(ops->storageType) { case LOG_UINT8: valuei = *(uint8_t *)&variable; break; case LOG_INT8: valuei = *(int8_t *)&variable; break; case LOG_UINT16: valuei = *(uint16_t *)&variable; break; case LOG_INT16: valuei = *(int16_t *)&variable; break; case LOG_UINT32: valuei = *(uint32_t *)&variable; break; case LOG_INT32: valuei = *(int32_t *)&variable; break; case LOG_FLOAT: valuei = *(float *)&variable; break; } if (ops->logType == LOG_FLOAT || ops->logType == LOG_FP16) { if (ops->storageType == LOG_FLOAT) valuef = *(float *)&variable; else valuef = valuei; // Try to append the next item to the packet. If we run out of space, // drop this and subsequent items. if (ops->logType == LOG_FLOAT) { if (!appendToPacket(&pk, &valuef, 4)) break; } else { valuei = single2half(valuef); if (!appendToPacket(&pk, &valuei, 2)) break; } } else //logType is an integer { if (!appendToPacket(&pk, &valuei, typeLength[ops->logType])) break; } ops = ops->next; } xSemaphoreGive(logLock); // Check if the connection is still up, oherwise disable // all the logging and flush all the CRTP queues. if (!crtpIsConnected()) { logReset(); crtpReset(); } else { crtpSendPacket(&pk); } }
void paramTOCProcess(int command) { int ptr = 0; char * group = ""; uint16_t n=0; uint16_t paramId=0; switch (command) { case CMD_GET_INFO: //Get info packet about the param implementation DEBUG_PRINT("Client uses old param API!\n"); ptr = 0; group = ""; p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.size=6; p.data[0]=CMD_GET_INFO; if (paramsCount < 255) { p.data[1]=paramsCount; } else { p.data[1]=255; } memcpy(&p.data[2], ¶msCrc, 4); crtpSendPacket(&p); break; case CMD_GET_ITEM: //Get param variable for (ptr=0; ptr<paramsLen; ptr++) //Ptr points a group { if (params[ptr].type & PARAM_GROUP) { if (params[ptr].type & PARAM_START) group = params[ptr].name; else group = ""; } else //Ptr points a variable { if (n==p.data[1]) break; n++; } } if (ptr<paramsLen) { p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.data[0]=CMD_GET_ITEM; p.data[1]=n; p.data[2]=params[ptr].type; p.size=3+2+strlen(group)+strlen(params[ptr].name); ASSERT(p.size <= CRTP_MAX_DATA_SIZE); // Too long! The name of the group or the parameter may be too long. memcpy(p.data+3, group, strlen(group)+1); memcpy(p.data+3+strlen(group)+1, params[ptr].name, strlen(params[ptr].name)+1); crtpSendPacket(&p); } else { p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.data[0]=CMD_GET_ITEM; p.size=1; crtpSendPacket(&p); } break; case CMD_GET_INFO_V2: //Get info packet about the param implementation ptr = 0; group = ""; p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.size=7; p.data[0]=CMD_GET_INFO_V2; memcpy(&p.data[1], ¶msCount, 2); memcpy(&p.data[3], ¶msCrc, 4); crtpSendPacket(&p); useV2 = true; break; case CMD_GET_ITEM_V2: //Get param variable memcpy(¶mId, &p.data[1], 2); for (ptr=0; ptr<paramsLen; ptr++) //Ptr points a group { if (params[ptr].type & PARAM_GROUP) { if (params[ptr].type & PARAM_START) group = params[ptr].name; else group = ""; } else //Ptr points a variable { if (n==paramId) break; n++; } } if (ptr<paramsLen) { p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.data[0]=CMD_GET_ITEM_V2; memcpy(&p.data[1], ¶mId, 2); p.data[3]=params[ptr].type; p.size=4+2+strlen(group)+strlen(params[ptr].name); ASSERT(p.size <= CRTP_MAX_DATA_SIZE); // Too long! The name of the group or the parameter may be too long. memcpy(p.data+4, group, strlen(group)+1); memcpy(p.data+4+strlen(group)+1, params[ptr].name, strlen(params[ptr].name)+1); crtpSendPacket(&p); } else { p.header=CRTP_HEADER(CRTP_PORT_PARAM, TOC_CH); p.data[0]=CMD_GET_ITEM_V2; p.size=1; crtpSendPacket(&p); } break; } }