/** @brief Send RAW response frame. * @param opcode uint8_t, Operation code. * @param frame uint8_t*, Command for this operation code. * @param length const uint8_t, Length of the payload. * @return Void. */ void send_raw_response(uint8_t opcode, uint8_t status, uint8_t * payload, const uint8_t length) { const int FrameLengthL = length + FRAME_STATIC_FIELD_LENGTH + FRAME_RESPONSE_PAYLOAD_OFFSET; uint8_t FrameL[(const int)FrameLengthL]; FrameL[FrameIndexes::Begin] = FRAME_SENTINEL; FrameL[FrameIndexes::FrmType] = FrameType::Response; FrameL[FrameIndexes::Length] = length + FRAME_RESPONSE_PAYLOAD_OFFSET; FrameL[FrameIndexes::OperationCode] = opcode; FrameL[FrameIndexes::StatusCode] = status; for (uint8_t index = 0; index < length; index++) { FrameL[index + FRAME_STATIC_FIELD_OFFSET + 1] = payload[index]; } uint8_t CRCL[FRAME_CRC_LEN] = { 0, 0 }; calculate_CRC(FrameL, (uint8_t)(FrameLengthL - FRAME_CRC_LEN), CRCL); for (uint8_t index = 0; index < FRAME_CRC_LEN; index++) { uint8_t FrmaeIndexL = index + FRAME_STATIC_FIELD_OFFSET + length + 1; FrameL[FrmaeIndexL] = CRCL[index]; } COM_PORT.write(FrameL, FrameLengthL); }
void add_crc(char *message) { int length; length = strlen(message); message[length] = calculate_CRC(message, length); message[length + 1] = '\0'; }
/** @brief Validate the CRC. * @param frame The frame string. * @return True if successful; or False if failed. */ bool validate_CRC(uint8_t * frame, uint8_t length) { uint8_t PayloadLen = length - FRAME_CRC_LEN; uint8_t CRCL[FRAME_CRC_LEN] = { 0, 0 }; calculate_CRC(frame, PayloadLen, CRCL); // Check odd byte and even bytes. return (frame[PayloadLen] == CRCL[0]) && (frame[PayloadLen + 1] == CRCL[1]); }
void send_command(t_serial_request *prq, t_shared_data *pshared) { char byte; char message[MAX_MSG_SIZE]; int sz, ctn; // enum eserial_state { ser_nothing, ser_waiting_response }; eserial_state ser_state; ser_state = ser_nothing; switch (prq->type) { case enothing: break; case eping: { while (pshared->pserial->read_next_byte(&byte)); // Empty the buffer snprintf(message, MAX_MSG_SIZE, "ping\n"); add_crc(message); pshared->pserial->write_serial_port(message, 1 + strlen(message)); ser_state = ser_waiting_response; } break; case einformation: { while (pshared->pserial->read_next_byte(&byte)); // Empty the buffer snprintf(message, MAX_MSG_SIZE, "get_params\n"); add_crc(message); pshared->pserial->write_serial_port(message, 1 + strlen(message)); ser_state = ser_waiting_response; } break; case ereport: { while (pshared->pserial->read_next_byte(&byte)); // Empty the buffer snprintf(message, MAX_MSG_SIZE, "get_report\n"); add_crc(message); pshared->pserial->write_serial_port(message, 1 + strlen(message)); ser_state = ser_waiting_response; } break; case eprogram: { snprintf(message, MAX_MSG_SIZE, "set_param %s\n", prq->command); add_crc(message); pshared->pserial->write_serial_port(message, 1 + strlen(message)); usleep(500000); ser_state = ser_nothing; } break; case eupdategui: default: break; } if (ser_state == ser_waiting_response) { // Get the bytes from the serial line. Wait a little if nothing is found. sz = 0; for (ctn = 0; !pshared->pserial->read_next_byte(&byte) && ctn < 10; ctn++) usleep(10000); while (sz < MAX_MSG_SIZE && byte != 0 && ctn < 10) // Is the end of the message { message[sz++] = byte; for (ctn = 0; !pshared->pserial->read_next_byte(&byte) && ctn < 10; ctn++) usleep(1000); } if (byte == 0 && sz > 0) { message[sz] = '\0'; if (!check_crc(message, sz)) { printf("Wrong CRC: %x / %x.\n", calculate_CRC(message, sz - 1), message[sz - 1]); return; } message[sz - 1] = '\0'; // Erase the CRC printf("<- Received a serial message: \"%s\".\n", message); LOCK; // Process the shit, like if it was a sewer pipe. switch (prq->type) { case enothing: break; case eping: { strncpy(pshared->bms_version, message, MAX_MSG_SIZE); } break; case einformation: { strncpy(pshared->param_msg, message, MAX_MSG_SIZE); pshared->pBMS->parse_BMS_params_string(&pshared->pBMS->m_params, pshared->param_msg); } break; case ereport: { strncpy(pshared->report_msg, message, MAX_MSG_SIZE); pshared->pBMS->parse_BMS_report_string(&pshared->pBMS->m_report, pshared->report_msg); } break; case eprogram: case eupdategui: default: break; } // This will trigger a screen refresh add_command_in_locked_area(eupdategui, " ", pshared); UNLOCK; } } }
bool check_crc(char *pmessage, int sz) { return (calculate_CRC(pmessage, sz - 1) == pmessage[sz - 1]); }