commit d45cc1f56f91ee9df944e57c09b8ea3fe2fe51d4 Author: Quinn Date: Mon Jun 10 18:25:55 2024 -0400 initial commit diff --git a/BluetoothSerialMessage.h b/BluetoothSerialMessage.h new file mode 100644 index 0000000..966bb9a --- /dev/null +++ b/BluetoothSerialMessage.h @@ -0,0 +1,64 @@ +#pragma once +#include "SerialMessage.h" +#include + +template +class BluetoothSerialMessage : public SerialMessage{ + public: + /** + * @brief Construct a new Bluetooth Serial Message object + */ + BluetoothSerialMessage(BluetoothSerial *serial); + + /** + * @brief Initialize the BluetoothSerialMessage object + */ + void Init(uint32_t baudRate = 115200) override; + + /** + * @brief prints the args array to the serial monitor + */ + void PrintArgs() override; + + private: + /** + * @brief reads the serial data and stores it in the data array + */ + char getChar() override; + uint32_t dataAvailable() override; + + BluetoothSerial *serial; + + +}; + +template +char BluetoothSerialMessage::getChar(){ + return serial->read(); +} + +template +uint32_t BluetoothSerialMessage::dataAvailable(){ + return serial->available(); +} + +template +BluetoothSerialMessage::BluetoothSerialMessage(BluetoothSerial *serial){ + this->serial = serial; +} + +template +void BluetoothSerialMessage::Init(uint32_t baudRate){ + serial->begin("MiniBot"); +} + +template +void BluetoothSerialMessage::PrintArgs(){ + serial->print("Current number of args: "); + serial->println(this->populatedArgs); + for (int i = 0; i < this->populatedArgs; i++) { + serial->print(this->args[i]); + serial->print(" "); + } + serial->println(); +} \ No newline at end of file diff --git a/Message.h b/Message.h new file mode 100644 index 0000000..d90ff5f --- /dev/null +++ b/Message.h @@ -0,0 +1,10 @@ +#pragma once + +namespace Message{ + enum Messages{ + MOTOR_READ, + MOTOR_WRITE, + CONSTANT_WRITE, + SET_POSE + }; +} \ No newline at end of file diff --git a/SerialMessage.h b/SerialMessage.h new file mode 100644 index 0000000..32b12e3 --- /dev/null +++ b/SerialMessage.h @@ -0,0 +1,225 @@ +/** + * @file SerialMessage.h + * @brief This file contains the SerialMessage class + * @details This file contains the SerialMessage class which is used to parse serial messages + * @version 1.0.0 + * @author Quinn Henthorne. Contact: quinn.henthorne@gmail.com +*/ + +#ifndef SERIALMESSAGE_H +#define SERIALMESSAGE_H + +#include "Arduino.h" + +template +class SerialMessage{ + public: + // @warning Never use this to construct a SerialMessage object + SerialMessage() = default; + /** + * @brief Construct a new Serial Message object + */ + SerialMessage(HardwareSerial *serial); + + /** + * @brief Initialize the SerialMessage object + */ + virtual void Init(unsigned int baud_rate = 115200); + + /** + * @brief Update the SerialMessage object and parse any data that's available + */ + void Update(); + + /** + * @brief Returns true if there is new data available + * @return true if there is new data available + */ + bool IsNewData(); + + /** + * @brief Clears the new data flag + */ + virtual void ClearNewData(); + + /** + * @brief Return a pointer to the args array + * @return a pointer to the args array + */ + uint32_t * GetArgs(); + + /** + * @brief Returns the number of args that have been populated for the current message + * @return the number of args that have been populated for the current message + */ + int GetArgsLength(); + + /** + * @brief Returns the number of args that have been populated for the current message + * @return the number of args that have been populated for the current message + */ + int GetPopulatedArgs(); + + /** + * @brief Prints the args array to the serial monitor + */ + virtual void PrintArgs(); + + protected: + enum SerialState : uint8_t{ + IDLE, + NEW_DATA, + DATA_RECIEVED, + RECIEVE_IN_PROGRESS + }; + virtual void readSerial(); + virtual void parseData(); + /** + * @brief reads the serial data and stores it in the data array + * @return the next character in the serial buffer + */ + virtual char getChar(); + + /** + * @brief returns the number of bytes available in the serial buffer + * @return the number of bytes available in the serial buffer + */ + virtual uint32_t dataAvailable(); + + SerialState state{IDLE}; + char data[byteSize]; // an array to store the received data + char temp_data[byteSize]; // an array that will be used with strtok() + uint16_t ndx{0}; + static constexpr uint16_t args_length{30}; + uint16_t populatedArgs{0}; // the number of args that have been populated for the current message + uint32_t args[args_length]; + const char startMarker = '!'; + const char endMarker = ';'; + + private: + HardwareSerial *serial{nullptr}; +}; + +template +char SerialMessage::getChar(){ + return this->serial->read(); +} + +template +uint32_t SerialMessage::dataAvailable(){ + return this->serial->available(); +} + +template +SerialMessage::SerialMessage(HardwareSerial *serial) : + serial(serial){} + +template +void SerialMessage::Init(unsigned int baud_rate){ + this->serial->begin(baud_rate); +} + +template +void SerialMessage::readSerial(){ + char c; + + // read the incoming serial data: + while (this->dataAvailable() > 0 && this->state != SerialState::DATA_RECIEVED) { + // get the neext character in the serial buffer + c = this->getChar(); + // only execute this if the startMarker has been received + // if the incoming character is the endMarker clean up and set the flags + if (this->state == SerialState::RECIEVE_IN_PROGRESS) { + if (c == endMarker) { + data[ndx] = '\0'; // terminate the string + ndx = 0; + this->state = SerialState::DATA_RECIEVED; + } + // if the incoming character is not the endMarker + else { + // add it to the data array + data[ndx] = c; + ndx++; // increment the data array index + // if the index is greater than the maximum data array size, + // keep overwriting the last element until the endMarker is received. + if (ndx >= byteSize) { + ndx = byteSize - 1; + } + } + } + // if the incoming character is the startMarker, set the recvInProgress flag + else if (c == startMarker) { + this->state = SerialState::RECIEVE_IN_PROGRESS; + } + } +} + +template +void SerialMessage::parseData() { // split the data into its parts + this->populatedArgs = 0; // reset the populated args counter + char * indx; // this is used by strtok() as an index + int i = 0; + indx = strtok(temp_data, ","); // get the first part - the string + while(indx != NULL){ + this->args[i] = atoi(indx); + populatedArgs++; + i++; + indx = strtok(NULL, ","); // this continues where the previous call left off + } +} + +template +void SerialMessage::Update(){ + readSerial(); + if (this->state == SerialState::DATA_RECIEVED) { + // for debug only: + // Serial.print("Received:"); + // Serial.print(data); + // Serial.println(":End"); + strcpy(temp_data, data); + // this temporary copy is necessary to protect the original data + // because strtok() used in parseData() replaces the commas with \0 + parseData(); + //PrintArgs(); + this->state = SerialState::NEW_DATA; + } +} + +template +bool SerialMessage::IsNewData(){ + return this->state == SerialState::NEW_DATA; +} + +template +void SerialMessage::ClearNewData(){ + this->state = SerialState::IDLE; +} + +template +uint32_t * SerialMessage::GetArgs(){ + return args; +} + +template +int SerialMessage::GetArgsLength(){ + return args_length; +} + +template +int SerialMessage::GetPopulatedArgs(){ + return populatedArgs; +} + +template +void SerialMessage::PrintArgs(){ + return; + this->serial->print("Current number of args: "); + this->serial->println(this->populatedArgs); + for (int i = 0; i < populatedArgs; i++) { + this->serial->print(args[i]); + this->serial->print(" "); + } + this->serial->println(); +} + +#endif \ No newline at end of file diff --git a/USBMessage.h b/USBMessage.h new file mode 100644 index 0000000..9acabd3 --- /dev/null +++ b/USBMessage.h @@ -0,0 +1,53 @@ +#pragma once +#include "SerialMessage.h" +#include + +template +class USBMessage : public SerialMessage{ + public: + /** + * @brief Construct a new Bluetooth Serial Message object + */ + USBMessage(USBCDC *serial); + void Init(uint32_t baudRate = 115200) override; + /** + * @brief prints the args array to the serial monitor + */ + void PrintArgs() override; + protected: + char getChar() override; + uint32_t dataAvailable() override; + private: + USBCDC *serial; + + +}; + +template +char USBMessage::getChar(){ + return serial->read(); +} + +template +uint32_t USBMessage::dataAvailable(){ + return serial->available(); +} + +template +USBMessage::USBMessage(USBCDC *serial) : serial(serial){} + +template +void USBMessage::Init(uint32_t baudRate){ + serial->begin(); +} + +template +void USBMessage::PrintArgs(){ + serial->print("Current number of args: "); + serial->println(this->populatedArgs); + for (int i = 0; i < this->populatedArgs; i++) { + serial->print(this->args[i]); + serial->print(" "); + } + serial->println(); +} \ No newline at end of file