diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bdffccd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 LaCocoRoco + +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 THE +AUTHORS OR COPYRIGHT HOLDERS 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ed5819 --- /dev/null +++ b/README.md @@ -0,0 +1,446 @@ +# DataVisualizer +This library is intended to simplify the use from Microchip Data Visualizer via the Atmel Data Protocol. +The Atmel Data Protocol is a content independent protocol intended for transferring data from a target MCU to a host PC. +The connection can be established via a Serial Port or the Data Gateway Interface (EDBG-based Debugger). + +## Quick Guide +1. Download Michrochip Data Visualizer. `Link` +2. Download Arduino Data Visualizer Library. +3. Open Arduino, select default example, compile and upload project. +4. Open Data Visualizer, select Serial Port Panel and press Connect. + +## Known Issues +- No Y-Values displayed in Graph Visualization +> In the left Top Corner select Configuration. +> At the bottom in Configuration Window switch Theme (Dark/Light). +- Not all possible Graph Settings are available +> The Graph Module is bad supported. +> This is related to the Atmel Data Protocol. +- After connect there is a ADP Control Panel but nothing else +> This sometimes happens at a Baudrate of 9600. Just push Disconnect & Connect again. + +## Roadmap +- [x] Add Gateway Uart +- [x] Add Gateway Twi +- [x] Add Gateway Spi +- [x] Add Gateway Callabck +- [x] Add Module Info +- [x] Add Module Terminal +- [x] Add Module Graph +- [x] Add Module Graph Axis +- [x] Add Module Graph Axis Channel +- [x] Add Module Graph Axis Cursor +- [x] Add Module Dashboard +- [x] Add Module Dashboard Label +- [x] Add Module Dashboard Button +- [x] Add Module Dashboard Numeric Input +- [x] Add Module Dashboard Signal +- [x] Add Module Dashboard Radio Group +- [x] Add Module Dashboard Graph +- [ ] Add Module Dashboard Table +- [ ] Add Module Dashboard Check Box +- [ ] Add Module Dashboard Slider +- [ ] Add Module Dashboard Progress Bar +- [ ] Add Module Dashboard Segment Display +- [ ] Add Module Dashboard Pie Chart +- [ ] Add Module Dashboard Surface Grid +- [ ] Add Module Dashboard Rectangle + +## Reference +- `Data Visualizer User's Guid (HTML)` +- `Data Visualizer User's Guid (PDF)` +- `Microchip Data Visualizer` + + +## Usage +- [Gateway](#gateway) +- [Common](#common) +- [Info](#info) +- [Terminal](#terminal) +- [Graph](#graph) +- [Dashboard](#dashboard) +- [Literal](#literal) + +### Gateway +- #### Universal Asynchronous Receiver Transmitter (Serial) +```cpp +// Setup Uart Default (GATEWAY_SERIAL) +Visualizer.begin(GATEWAY_UART); + +// Setup Uart Customized +Serial.begin(DEFAULT_UART_BAUDRATE); +Visualizer.begin(&Serial); +``` + +- #### Two Wire Interface +```cpp +// Setup Twi Default +Visualizer.begin(GATEWAY_TWI); + +// Setup Twi Customized +Wire.begin(); +Visualizer.begin(&Wire, DEFAULT_TWI_ADDRESS); +``` + +- #### Serial Peripheral Interface +```cpp +// Setup Spi Default +Visualizer.begin(GATEWAY_SPI); + +// Setup Spi Customized +SPISettings settings(DEFAULT_SPI_FREQUENCY, MSBFIRST, SPI_MODE0); +SPI.begin(); +Visualizer.begin(&SPI, settings, SS); +``` + +- #### External Interface +```cpp +// Setup External +Visualizer.begin(GATEWAY_EXTERN); +Visualizer.onTransmit(&transmit); +Visualizer.onReceive(&receive); +Visualizer.onTransceive(&transceive); + +// External Transmit +void transmit(uint8_t* txBuffer, uint16_t length); + +// External Receive +uint16_t receive(uint8_t* rxBuffer, uint16_t length); + +// External Transceive +uint16_t transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length); + +``` + +### Common +```cpp +// Element Setup Handler Configuration None +if(Visualizer.setup(CONFIGURATION_NONE)) { + // initialize elements +} + +// Element Setup Handler Configuration Autostart +if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + // initialize elements +} + +// Data Visualizer Handshake Request + if(Visualizer.request()) { + // handshake accepted + } + +// Data Visualizer Reset +Visualizer.reset(); + +// Request Data From Data Visualizer +Visualizer.refresh(); +``` + +### Info +```cpp +// Add Atmel Data Protocol Environment Information +Visualizer.addInfo("My Visualizer", "My Environment"); +``` + +### Terminal +```cpp +// Add Terminal +Terminal terminal = Visualizer.addTerminal("My Terminal"); + +// Read Single Byte From Terminal +while(terminal.available()) { + char c = terminal.read(); +} + +// Read All Bytes From Terminal +while(terminal.available()) { + char text[terminal.available()]; + terminal.read(text); +} + +// Print Data In Terminal Console +terminal.print("My Text"); + +// Print Data In Terminal Console Carriage Return +terminal.println("My Text"); +``` + +### Graph +```cpp +// Add Graph +Graph graph = Visualizer.addGraph("My Graph"); + +// Add Axis +GraphAxis graphAxis = graph.addAxis("My Axis"); + +// Add Channel +GraphAxisChannel graphAxisChannel = graphAxis.addChannel("My Channel"); + +// Add Cursor +GraphAxisCursor graphAxisCursor = graphAxis.addCursor("My Cursor"); + +// Send Data To Channel +graphAxisChannel.write(number); + +// Cursor Data Changed +GraphAxisCursor.feed(); + +// Read Data From Cursor +GraphAxisCursor.read(); +``` + +### Dashboard +```cpp +// Add Dashboard +Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); +``` +- #### Label +```cpp +// Config Label +ConfigDashboardLabel configDashboardLabel = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 100, + .height = 25, + .fontSize = 20, + .attribute = BOLD_ON_ITALIC_OFF, + .aligmentHorisontal = HORISONTAL_ALIGNMENT_CENTER, + .aligmentVertical = VERTICAL_ALIGNMENT_CENTER, + .backgroundColor = COLOR_WHITE, + .backgroundAlpha = 0, + .forgroundColor = COLOR_BLACK, + .forgroundAlpha = 255 +}; + +// Add Label +dashboard.addLabel("MyLabel", configDashboardLabel); +``` +- #### Button +```cpp +// Config Button +ConfigDashboardButton configDashboardButton = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 150, + .height = 50, + .fontSize = 20 +}; + +// Add Button +DashboardButton dashboardButton = dashboard.addButton("MyButton", configDashboardButton); + +// Add Toggle Button +DashboardButton dashboardButton = dashboard.addButton("MyOn", "MyOff", configDashboardButton); + +// Button Pressed +dashboardButton.pressed(); + +// Button Toggled State +dashboardButton.toggled(); +``` +- #### Numeric Input +```cpp +// Config Numeric Input +ConfigDashboardNumericInput configDashboardNumericInput = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 150, + .height = 50, + .fontSize = 20 +}; + +// Add Numeric Input +DashboardNumericInput dashboardNumericInput = dashboard.addNumericInput(configDashboardNumericInput); + +// Numeric Input New Data +dashboardNumericInput.feed(); + +// Read Numeric Data +dashboardNumericInput.read(); +``` +- #### Signal +```cpp +// Config Signal +ConfigDashboardSignal configDashboardSignal = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 50, + .height = 50, + .onColor = COLOR_RED, + .onAlpha = 255, + .offColor = COLOR_GREEN, + .offAlpha = 255 +}; + +// Add Signal +DashboardSignal dashboardSignal = dashboard.addSignal(configDashboardSignal); + +// Set Signal On +dashboardSignal.on(); + +// Set Signal Off +dashboardSignal.off(); +``` +- #### Radio Group +```cpp +// Config Radio Group +ConfigDashboardRadioGroup configDashboardRadioGroup = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 15, + .height = 150, + .sizeItems = 10, + .numberItems = 6, + .orientation = HORIZONTAL +}; + +// Add Signal +DashboardRadioGroup dashboardRadioGroup = dashboard.addRadioGroup(configDashboardRadioGroup); + +// Radio Group New Data +dashboardRadioGroup.feed(); + +// Read Radio Group Data +dashboardRadioGroup.selected(); +``` +- #### Graph +```cpp +// Config Graph +ConfigDashboardGraph configDashboardGraph = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 400, + .height = 200, + .titleColor = COLOR_WHITE, + .backgroundColor = COLOR_BLACK, + .graphBackgroundColor = COLOR_BLACK, + .plotCount = 1, + .xMinimum = 0, + .xMaximum = 10, + .yMinimum = -1000, + .yMaximum = +1000, + .mouseInteraction = true, + .fitToRight = false, + .autoscale = false, + .scrollByTime = true, + .showPlot = true, + .showPoints = false +}; + +// Add Graph +DashboardGraph dashboardGraph = dashboard.addGraph("My Graph", configDashboardGraph); + +// Add Channel +DashboardGraphChannel dashboardGraphChannel = dashboardGraph.addChannel("My Channel A"); + +// Read Radio Group Data +dashboardGraphChannel.write(number); +``` +- #### Predefined Configuration +```cpp +/* Data Visualizer has the possibility to predefine a Dashboard. + * 1. Start Data Visualizer. + * 2. On the top left corner press "Configuration". + * 3. In Modules select "Visualization" and then "Custom Dashboard". + * 4. In the "Dashboard Panel" on the bottom left press "Edit". + * 5. In the "Dashboard Panel" on the right side expand "Elements". + * 6. Create your own Dashboard. + * 7. In the "Dashboard Panel" on the bottom press "Save". + * 8. The configuration per element will be saved as byte arrays. + * 9. Use the configuration file in combination with the Visualizer. + **/ + +// Dashboard Configuration Example Button +byte configDashboardButton[] = { + 0, // Dashboard ID + 0, // Element ID + DB_TYPE_BUTTON, // Element Type + 0, // Z-Index (GUI stack order) + 50, 0, // X-coordinate + 50, 0, // Y-coordinate + 150, 0, // Width + 50, 0, // Height + 20, // Font Size + 'M', 'y', 'B', 'u', 't', 't', 'o', 'n', '\0', // Text + 0, +}; + +// Add Button Via Configuration +DashboardButton dashboardButton = dashboard.addButton(configDashboardButton); +``` + +### Literal +```cpp +CONFIGURATION_NONE +CONFIGURATION_AUTOSTART + +GATEWAY_EXTERNAL +GATEWAY_TWI +GATEWAY_SPI +GATEWAY_UART +GATEWAY_SERIAL + +BAUDRATE_9600 +BAUDRATE_19200 +BAUDRATE_38400 +BAUDRATE_57600 +BAUDRATE_115200 +BAUDRATE_230400 +BAUDRATE_500000 +BAUDRATE_1000000 +BAUDRATE_2000000 + +COLOR_WHITE +COLOR_BLACK +COLOR_SILVER +COLOR_GRAY +COLOR_MAROON +COLOR_RED +COLOR_PURPLE +COLOR_FUCHSIA +COLOR_GREEN +COLOR_LIME +COLOR_OLIVE +COLOR_YELLOW +COLOR_NAVY +COLOR_BLUE +COLOR_TEAL +COLOR_AQUA +COLOR_ORANGE + +BOLD_OFF_ITALIC_OFF +BOLD_ON_ITALIC_OFF +BOLD_OFF_ITALIC_ON +BOLD_ON_ITALIC_ON + +HORISONTAL_ALIGNMENT_LEFT +HORISONTAL_ALIGNMENT_CENTER +HORISONTAL_ALIGNMENT_RIGHT + +VERTICAL_ALIGNMENT_TOP +VERTICAL_ALIGNMENT_CENTER +VERTICAL_ALIGNMENT_BOTTOM + +HORIZONTAL +VERTICAL + +DB_TYPE_LABEL +DB_TYPE_BUTTON +DB_TYPE_TEXT +DB_TYPE_SIGNAL +DB_TYPE_RADIOGROUP + +DEFAULT_UART_BAUDRATE +DEFAULT_UART_TIMEOUT +DEFAULT_TWI_ADDRESS +DEFAULT_TWI_FREQUENCY +DEFAULT_TWI_TIMEOUT +DEFAULT_SPI_FREQUENCY +DEFAULT_VIEW +``` \ No newline at end of file diff --git a/examples/defaultExample/defaultExample.ino b/examples/defaultExample/defaultExample.ino new file mode 100644 index 0000000..cd1b7ab --- /dev/null +++ b/examples/defaultExample/defaultExample.ino @@ -0,0 +1,54 @@ +#include + +Terminal terminal; +GraphAxisChannel graphAxisChannel; +GraphAxisCursor cursor; +int valueChannel, valueCursor; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + /****************************************************************/ + /* WARNING: Initializing elements blocks process. */ + /****************************************************************/ + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + /* add atmel data protocol environment info */ + Visualizer.addInfo("My Visualizer", "My Environment"); + /* add terminal */ + terminal = Visualizer.addTerminal("My Terminal"); + /* add graph, axis, channel & cursor */ + Graph graph = Visualizer.addGraph("My Graph"); + GraphAxis axis = graph.addAxis("My Axis"); + graphAxisChannel = axis.addChannel("My Channel"); + cursor = axis.addCursor("My Cursor"); + } + + /* only read data if necessary */ + while(terminal.available()) { + /* read text from terminal */ + char text[terminal.available()]; + terminal.read(text); + /* convert text into integer */ + String string = String(text); + valueChannel = string.toInt(); + /* write text to terminal console */ + string = "Terminal Input: " + string; + terminal.println(string.c_str()); + + } + + /* only write data if value changed */ + if(cursor.read() != valueCursor) { + /* read value from cursor */ + valueCursor = cursor.read(); + /* write cursor value to terminal */ + String string = String(valueCursor); + string = "Cursor Input: " + string; + terminal.println(string.c_str()); + } + + /* write terminal value to channel */ + graphAxisChannel.write(valueChannel); +} \ No newline at end of file diff --git a/examples/defaultExamplePredefinedDashboard/defaultExamplePredefinedDashboard.ino b/examples/defaultExamplePredefinedDashboard/defaultExamplePredefinedDashboard.ino new file mode 100644 index 0000000..2a89142 --- /dev/null +++ b/examples/defaultExamplePredefinedDashboard/defaultExamplePredefinedDashboard.ino @@ -0,0 +1,135 @@ +#include + +/* Data Visualizer has the possibility to predefine a Dashboard. + * 1. Start Data Visualizer. + * 2. On the top left corner press "Configuration". + * 3. In Modules select "Visualization" and then "Custom Dashboard". + * 4. In the "Dashboard Panel" on the bottom left press "Edit". + * 5. In the "Dashboard Panel" on the right side expand "Elements". + * 6. Create your own Dashboard. + * 7. In the "Dashboard Panel" on the bottom press "Save". + * 8. The configuration per element will be saved as byte arrays. + * 9. Use the configuration file in combination with the Visualizer. + **/ + +DashboardNumericInput dashboardNumericInput; +DashboardButton dashboardButton; +DashboardGraphChannel dashboardGraphChannel; +int value; + +void setup() { + value = 0; + + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + /****************************************************************/ + /* WARNING: Initializing elements blocks process. */ + /****************************************************************/ + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + + byte configDashboardLabelTop[] = { + 0, // Dashboard ID + 0, // Element ID + DB_TYPE_LABEL, // Element Type + 0, // Z-Index (GUI stack order) + 50, 0, // X-coordinate + 50, 0, // Y-coordinate + 250, 0, // Width + 30, 0, // Height + 20, // Font Size + 1, + 0, // Horizontal Alignment + 0, // Vertical Alignment + 0, 255, 255, 255, // Background Color + 255, 0, 0, 0, // Foreground Color + 'M', 'y', ' ', 'P', 'r', 'e', 'd', 'e', 'f', 'i', 'n', 'e', 'd', ' ', 'D', 'a', 's', 'h', 'b', 'o', 'a', 'r', 'd', '\0', // Text + }; + dashboard.addLabel(configDashboardLabelTop); + + byte configDashboardGraph[] = { + 0, // Dashboard ID + 1, // Element ID + DB_TYPE_GRAPH, // Element Type + 0, // Z-Index (GUI stack order) + 50, 0, // X-coordinate + 80, 0, // Y-coordinate + 104, 1, // Width + 250, 0, // Height + 255, 255, 255, // Title color + 0, 0, 0, // Background color + 20, 20, 20, // Graph background color + 'M', 'y', ' ', 'G', 'r', 'a', 'p', 'h', '\0', // Title + 1, // Number of plots + 0, 0, 0, 0, // X Minimum + 0, 0, 32, 65, // X Maximum + 0, 0, 122, 196, // Y Minimum + 0, 0, 122, 68, // Y Maximum + 1, + 1, + }; + DashboardGraph dashboardGraph = dashboard.addGraph(configDashboardGraph); + dashboardGraphChannel = dashboardGraph.addChannel("My Channel"); + + byte configDashboardNumericInput[] = { + 0, // Dashboard ID + 2, // Element ID + DB_TYPE_TEXT, // Element Type + 1, // Z-Index (GUI stack order) + 210, 0, // X-coordinate + 134, 1, // Y-coordinate + 60, 0, // Width + 20, 0, // Height + 24, 252, 255, 255, // Minimum + 232, 3, 0, 0, // Maximum + 0, 0, 0, 0, // Value + }; + dashboardNumericInput = dashboard.addNumericInput(configDashboardNumericInput); + + byte configDashboardLabelValue[] = { + 0, // Dashboard ID + 3, // Element ID + DB_TYPE_LABEL, // Element Type + 0, // Z-Index (GUI stack order) + 50, 0, // X-coordinate + 134, 1, // Y-coordinate + 160, 0, // Width + 20, 0, // Height + 15, // Font Size + 0, + 0, // Horizontal Alignment + 1, // Vertical Alignment + 0, 255, 255, 255, // Background Color + 255, 0, 0, 0, // Foreground Color + 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', ' ', 'G', 'r', 'a', 'p', 'h', ' ', 'V', 'a', 'l', 'u', 'e', ':', '\0', // Text + }; + dashboard.addLabel(configDashboardLabelValue); + + byte configDashboardButton[] = { + 0, // Dashboard ID + 4, // Element ID + DB_TYPE_BUTTON, // Element Type + 0, // Z-Index (GUI stack order) + 44, 1, // X-coordinate + 134, 1, // Y-coordinate + 110, 0, // Width + 20, 0, // Height + 12, // Font Size + 'R', 'e', 's', 'e', 't', ' ', 'G', 'r', 'a', 'p', 'h', ' ', 'V', 'a', 'l', 'u', 'e', '\0', // Text + 0, + }; + dashboardButton = dashboard.addButton(configDashboardButton); + } + + if(dashboardNumericInput.feed()) { + value = dashboardNumericInput.read(); + } + + if(dashboardButton.pressed()) { + value = 0; + } + + dashboardGraphChannel.write(value); +} \ No newline at end of file diff --git a/examples/gatewaySetupExternal/gatewaySetupExternal.ino b/examples/gatewaySetupExternal/gatewaySetupExternal.ino new file mode 100644 index 0000000..e71bfee --- /dev/null +++ b/examples/gatewaySetupExternal/gatewaySetupExternal.ino @@ -0,0 +1,24 @@ +#include + +void transmit(uint8_t* txBuffer, uint16_t length) { + +} + +uint16_t receive(uint8_t* rxBuffer, uint16_t length) { + +} + +uint16_t transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length) { + +} + +void setup() { + Visualizer.begin(GATEWAY_EXTERN); + Visualizer.onTransmit(&transmit); + Visualizer.onReceive(&receive); + Visualizer.onTransceive(&transceive); +} + +void loop() { + +} \ No newline at end of file diff --git a/examples/gatewaySetupSpi/gatewaySetupSpi.ino b/examples/gatewaySetupSpi/gatewaySetupSpi.ino new file mode 100644 index 0000000..7aac78d --- /dev/null +++ b/examples/gatewaySetupSpi/gatewaySetupSpi.ino @@ -0,0 +1,9 @@ +#include + +void setup() { + Visualizer.begin(GATEWAY_SPI); +} + +void loop() { + +} diff --git a/examples/gatewaySetupSpiCustomized/gatewaySetupSpiCustomized.ino b/examples/gatewaySetupSpiCustomized/gatewaySetupSpiCustomized.ino new file mode 100644 index 0000000..c515ea0 --- /dev/null +++ b/examples/gatewaySetupSpiCustomized/gatewaySetupSpiCustomized.ino @@ -0,0 +1,13 @@ +#include + +void setup() { + SPISettings settings(DEFAULT_SPI_FREQUENCY, MSBFIRST, SPI_MODE0); + + SPI.begin(); + + Visualizer.begin(&SPI, settings, SS); +} + +void loop() { + +} diff --git a/examples/gatewaySetupTwi/gatewaySetupTwi.ino b/examples/gatewaySetupTwi/gatewaySetupTwi.ino new file mode 100644 index 0000000..2c146fc --- /dev/null +++ b/examples/gatewaySetupTwi/gatewaySetupTwi.ino @@ -0,0 +1,9 @@ +#include + +void setup() { + Visualizer.begin(GATEWAY_TWI); +} + +void loop() { + +} \ No newline at end of file diff --git a/examples/gatewaySetupTwiCustomized/gatewaySetupTwiCustomized.ino b/examples/gatewaySetupTwiCustomized/gatewaySetupTwiCustomized.ino new file mode 100644 index 0000000..0526fde --- /dev/null +++ b/examples/gatewaySetupTwiCustomized/gatewaySetupTwiCustomized.ino @@ -0,0 +1,11 @@ +#include + +void setup() { + Wire.begin(); + + Visualizer.begin(&Wire, DEFAULT_TWI_ADDRESS); +} + +void loop() { + +} \ No newline at end of file diff --git a/examples/gatewaySetupUart/gatewaySetupUart.ino b/examples/gatewaySetupUart/gatewaySetupUart.ino new file mode 100644 index 0000000..c1ed49c --- /dev/null +++ b/examples/gatewaySetupUart/gatewaySetupUart.ino @@ -0,0 +1,9 @@ +#include + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + +} diff --git a/examples/gatewaySetupUartCustomized/gatewaySetupUartCustomized.ino b/examples/gatewaySetupUartCustomized/gatewaySetupUartCustomized.ino new file mode 100644 index 0000000..04c17aa --- /dev/null +++ b/examples/gatewaySetupUartCustomized/gatewaySetupUartCustomized.ino @@ -0,0 +1,11 @@ +#include + +void setup() { + Serial.begin(DEFAULT_UART_BAUDRATE); + + Visualizer.begin(&Serial); +} + +void loop() { + +} diff --git a/examples/moduleDashboard/moduleDashboard.ino b/examples/moduleDashboard/moduleDashboard.ino new file mode 100644 index 0000000..42b93a3 --- /dev/null +++ b/examples/moduleDashboard/moduleDashboard.ino @@ -0,0 +1,14 @@ +#include + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + /****************************************************************/ + /* WARNING: Initializing elements blocks process. */ + /****************************************************************/ + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + } +} \ No newline at end of file diff --git a/examples/moduleDashboardButton/moduleDashboardButton.ino b/examples/moduleDashboardButton/moduleDashboardButton.ino new file mode 100644 index 0000000..d0af7a6 --- /dev/null +++ b/examples/moduleDashboardButton/moduleDashboardButton.ino @@ -0,0 +1,30 @@ +#include + +Terminal terminal; +DashboardButton dashboardButton; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + terminal = Visualizer.addTerminal("My Terminal"); + + ConfigDashboardButton configDashboardButton = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 150, + .height = 50, + .fontSize = 20 + }; + + dashboardButton = dashboard.addButton("My Button", configDashboardButton); + } + + if(dashboardButton.pressed()) { + terminal.println("My Button Pressed"); + } +} \ No newline at end of file diff --git a/examples/moduleDashboardButtonToggled/moduleDashboardButtonToggled.ino b/examples/moduleDashboardButtonToggled/moduleDashboardButtonToggled.ino new file mode 100644 index 0000000..386945e --- /dev/null +++ b/examples/moduleDashboardButtonToggled/moduleDashboardButtonToggled.ino @@ -0,0 +1,34 @@ +#include + +Terminal terminal; +DashboardButton dashboardButton; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + terminal = Visualizer.addTerminal("My Terminal"); + + ConfigDashboardButton configDashboardButton = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 150, + .height = 50, + .fontSize = 20 + }; + + dashboardButton = dashboard.addButton("MyOn", "MyOff", configDashboardButton); + } + + if(dashboardButton.pressed()) { + if(dashboardButton.toggled()) { + terminal.println("My Button Toggled On"); + } else { + terminal.println("My Button Toggled Off"); + } + } +} \ No newline at end of file diff --git a/examples/moduleDashboardGraph/moduleDashboardGraph.ino b/examples/moduleDashboardGraph/moduleDashboardGraph.ino new file mode 100644 index 0000000..68f0706 --- /dev/null +++ b/examples/moduleDashboardGraph/moduleDashboardGraph.ino @@ -0,0 +1,41 @@ +#include + +DashboardGraphChannel dashboardGraphChannel; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + + ConfigDashboardGraph configDashboardGraph = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 400, + .height = 200, + .titleColor = COLOR_WHITE, + .backgroundColor = COLOR_BLACK, + .graphColor = COLOR_BLACK, + .plotCount = 1, + .xMinimum = 0, + .xMaximum = 10, + .yMinimum = -1000, + .yMaximum = +1000, + .mouseInteraction = true, + .fitToRight = false, + .autoscale = false, + .scrollByTime = true, + .showPlot = true, + .showPoints = false + }; + + DashboardGraph dashboardGraph = dashboard.addGraph("My Graph", configDashboardGraph); + + dashboardGraphChannel = dashboardGraph.addChannel("My Channel"); + } + + dashboardGraphChannel.write(500); +} \ No newline at end of file diff --git a/examples/moduleDashboardLabel/moduleDashboardLabel.ino b/examples/moduleDashboardLabel/moduleDashboardLabel.ino new file mode 100644 index 0000000..af1fbbc --- /dev/null +++ b/examples/moduleDashboardLabel/moduleDashboardLabel.ino @@ -0,0 +1,31 @@ +#include + +Terminal terminal; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + + ConfigDashboardLabel configDashboardLabel = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 100, + .height = 25, + .fontSize = 20, + .attribute = BOLD_ON_ITALIC_OFF, + .aligmentHorisontal = HORISONTAL_ALIGNMENT_CENTER, + .aligmentVertical = VERTICAL_ALIGNMENT_CENTER, + .backgroundColor = COLOR_WHITE, + .backgroundAlpha = 0, + .forgroundColor = COLOR_BLACK, + .forgroundAlpha = 255 + }; + + dashboard.addLabel("MyLabel", configDashboardLabel); + } +} \ No newline at end of file diff --git a/examples/moduleDashboardNumericInput/moduleDashboardNumericInput.ino b/examples/moduleDashboardNumericInput/moduleDashboardNumericInput.ino new file mode 100644 index 0000000..78f40a0 --- /dev/null +++ b/examples/moduleDashboardNumericInput/moduleDashboardNumericInput.ino @@ -0,0 +1,33 @@ +#include + +Terminal terminal; +DashboardNumericInput dashboardNumericInput; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + terminal = Visualizer.addTerminal("My Terminal"); + + ConfigDashboardNumericInput configDashboardNumericInput = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 100, + .height = 20, + .minimum = -100, + .maximum = +100, + .value = 0 + }; + + dashboardNumericInput = dashboard.addNumericInput(configDashboardNumericInput); + } + + if(dashboardNumericInput.feed()) { + terminal.print("Numeric Input Value: "); + terminal.println(dashboardNumericInput.read()); + } +} \ No newline at end of file diff --git a/examples/moduleDashboardRadioGroup/moduleDashboardRadioGroup.ino b/examples/moduleDashboardRadioGroup/moduleDashboardRadioGroup.ino new file mode 100644 index 0000000..1caf12b --- /dev/null +++ b/examples/moduleDashboardRadioGroup/moduleDashboardRadioGroup.ino @@ -0,0 +1,32 @@ +#include + +Terminal terminal; +DashboardRadioGroup dashboardRadioGroup; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + terminal = Visualizer.addTerminal("My Terminal"); + + ConfigDashboardRadioGroup configDashboardRadioGroup = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 15, + .height = 150, + .sizeItems = 10, + .numberItems = 6, + .orientation = VERTICAL + }; + + dashboardRadioGroup = dashboard.addRadioGroup(configDashboardRadioGroup); + } + + if(dashboardRadioGroup.feed()) { + terminal.println(dashboardRadioGroup.selected()); + } +} \ No newline at end of file diff --git a/examples/moduleDashboardSignal/moduleDashboardSignal.ino b/examples/moduleDashboardSignal/moduleDashboardSignal.ino new file mode 100644 index 0000000..6779ef6 --- /dev/null +++ b/examples/moduleDashboardSignal/moduleDashboardSignal.ino @@ -0,0 +1,42 @@ +#include + +DashboardSignal dashboardSignal; + +long tick; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + /****************************************************************/ + /* WARNING: Initializing elements blocks process. */ + /****************************************************************/ + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Dashboard dashboard = Visualizer.addDashboard("My Dashboard"); + + ConfigDashboardSignal configDashboardSignal = { + .zIndex = 0, + .x = 50, + .y = 50, + .width = 50, + .height = 50, + .onColor = COLOR_RED, + .onAlpha = 255, + .offColor = COLOR_GREEN, + .offAlpha = 255 + }; + + dashboardSignal = dashboard.addSignal(configDashboardSignal); + } + + tick++; + + if(tick > 2000) tick = 0; + + if(tick < 1000) { + dashboardSignal.on(); + } else { + dashboardSignal.off(); + } +} \ No newline at end of file diff --git a/examples/moduleGraph/moduleGraph.ino b/examples/moduleGraph/moduleGraph.ino new file mode 100644 index 0000000..a9a77e4 --- /dev/null +++ b/examples/moduleGraph/moduleGraph.ino @@ -0,0 +1,23 @@ +#include + +GraphAxisChannel graphAxisChannel; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + /****************************************************************/ + /* WARNING: Initializing elements blocks process. */ + /****************************************************************/ + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Graph graph = Visualizer.addGraph("My Graph"); + GraphAxis graphAxis = graph.addAxis("My Axis"); + graphAxisChannel = graphAxis.addChannel("My Channel"); + } + + /****************************************************************/ + /* Write data to channel. */ + /****************************************************************/ + graphAxisChannel.write(10000); +} \ No newline at end of file diff --git a/examples/moduleInfo/moduleInfo.ino b/examples/moduleInfo/moduleInfo.ino new file mode 100644 index 0000000..5e6ac2f --- /dev/null +++ b/examples/moduleInfo/moduleInfo.ino @@ -0,0 +1,14 @@ +#include + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + /****************************************************************/ + /* WARNING: Initializing elements blocks process. */ + /****************************************************************/ + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + Visualizer.addInfo("My Visualizer", "My Environment"); + } +} \ No newline at end of file diff --git a/examples/moduleTerminal/moduleTerminal.ino b/examples/moduleTerminal/moduleTerminal.ino new file mode 100644 index 0000000..abed77d --- /dev/null +++ b/examples/moduleTerminal/moduleTerminal.ino @@ -0,0 +1,24 @@ +#include + +Terminal terminal; + +void setup() { + Visualizer.begin(GATEWAY_SERIAL); +} + +void loop() { + /****************************************************************/ + /* WARNING: Initializing elements blocks process. */ + /****************************************************************/ + if(Visualizer.setup(CONFIGURATION_AUTOSTART)) { + terminal = Visualizer.addTerminal("My Terminal"); + } + + /****************************************************************/ + /* Read data from terminal and write to terminal console */ + /****************************************************************/ + while(terminal.available()) { + char c = terminal.read(); + terminal.println(c); + } +} \ No newline at end of file diff --git a/extras/DataVisualizer.pdf b/extras/DataVisualizer.pdf new file mode 100644 index 0000000..568b542 Binary files /dev/null and b/extras/DataVisualizer.pdf differ diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..99b6791 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,196 @@ +###################################### +# Main KEYWORD1 # +###################################### +Visualizer KEYWORD1 + +###################################### +# Classes KEYWORD1 # +###################################### +Terminal KEYWORD1 +Graph KEYWORD1 +GraphAxis KEYWORD1 +GraphAxisChannel KEYWORD1 +GraphAxisCursor KEYWORD1 +Dashboard KEYWORD1 +DashboardLabel KEYWORD1 +DashboardButton KEYWORD1 +DashboardNumericInput KEYWORD1 +DashboardSignal KEYWORD1 +DashboardRadioGroup KEYWORD1 +DashboardGraph KEYWORD1 +DashboardGraphChannel KEYWORD1 + +###################################### +# Configuration KEYWORD1 # +###################################### +ConfigDashboardLabel KEYWORD1 +ConfigDashboardButton KEYWORD1 +ConfigDashboardNumericInput KEYWORD1 +ConfigDashboardSignal KEYWORD1 +ConfigDashboardRadioGroup KEYWORD1 +ConfigDashboardGraph KEYWORD1 + +###################################### +# Interface KEYWORD2 # +###################################### +transmit KEYWORD2 +receive KEYWORD2 +transceive KEYWORD2 +onTransmit KEYWORD2 +onReceive KEYWORD2 +onTransceive KEYWORD2 + +###################################### +# Visualizer KEYWORD2 # +###################################### +request KEYWORD2 +reset KEYWORD2 +refresh KEYWORD2 +addInfo KEYWORD2 +addTerminal KEYWORD2 +addGraph KEYWORD2 +addDashboard KEYWORD2 + +###################################### +# Terminal KEYWORD2 # +###################################### +available KEYWORD2 +read KEYWORD2 +print KEYWORD2 +println KEYWORD2 + +###################################### +# Graph KEYWORD2 # +###################################### +addAxis KEYWORD2 + +###################################### +# GraphAxis KEYWORD2 # +###################################### +addChannel KEYWORD2 +addCursor KEYWORD2 + +###################################### +# GraphAxisChannel KEYWORD2 # +###################################### +write KEYWORD2 + +###################################### +# GraphAxisCursor KEYWORD2 # +###################################### +read KEYWORD2 +feed KEYWORD2 + +###################################### +# Dashboard KEYWORD2 # +###################################### +addButton KEYWORD2 +addNumericInput KEYWORD2 +addLabel KEYWORD2 +addSignal KEYWORD2 +addRadioGroup KEYWORD2 +addGraph + +###################################### +# DashboardButton KEYWORD2 # +###################################### +pressed KEYWORD2 +toggled KEYWORD2 + +###################################### +# DashboardNumericalInput KEYWORD2 # +###################################### +read KEYWORD2 +feed KEYWORD2 + +###################################### +# DashboardSignal KEYWORD2 # +###################################### +on KEYWORD2 +off KEYWORD2 + +###################################### +# DashboardRadioGroup KEYWORD2 # +###################################### +selected KEYWORD2 +feed KEYWORD2 + +###################################### +# DashboardGraph KEYWORD2 # +###################################### +addChannel KEYWORD2 + +###################################### +# DashboardGraphChannel KEYWORD2 # +###################################### +write KEYWORD2 + +###################################### +# General LITERAL1 # +###################################### +CONFIGURATION_NONE LITERAL1 +CONFIGURATION_AUTOSTART LITERAL1 + +GATEWAY_EXTERNAL LITERAL1 +GATEWAY_TWI LITERAL1 +GATEWAY_SPI LITERAL1 +GATEWAY_UART LITERAL1 +GATEWAY_SERIAL LITERAL1 + +BAUDRATE_9600 LITERAL1 +BAUDRATE_19200 LITERAL1 +BAUDRATE_38400 LITERAL1 +BAUDRATE_57600 LITERAL1 +BAUDRATE_115200 LITERAL1 +BAUDRATE_230400 LITERAL1 +BAUDRATE_500000 LITERAL1 +BAUDRATE_1000000 LITERAL1 +BAUDRATE_2000000 LITERAL1 + +COLOR_WHITE LITERAL1 +COLOR_BLACK LITERAL1 +COLOR_SILVER LITERAL1 +COLOR_GRAY LITERAL1 +COLOR_MAROON LITERAL1 +COLOR_RED LITERAL1 +COLOR_PURPLE LITERAL1 +COLOR_FUCHSIA LITERAL1 +COLOR_GREEN LITERAL1 +COLOR_LIME LITERAL1 +COLOR_OLIVE LITERAL1 +COLOR_YELLOW LITERAL1 +COLOR_NAVY LITERAL1 +COLOR_BLUE LITERAL1 +COLOR_TEAL LITERAL1 +COLOR_AQUA LITERAL1 +COLOR_ORANGE LITERAL1 + +BOLD_OFF_ITALIC_OFF LITERAL1 +BOLD_ON_ITALIC_OFF LITERAL1 +BOLD_OFF_ITALIC_ON LITERAL1 +BOLD_ON_ITALIC_ON LITERAL1 + +HORISONTAL_ALIGNMENT_LEFT LITERAL1 +HORISONTAL_ALIGNMENT_CENTER LITERAL1 +HORISONTAL_ALIGNMENT_RIGHT LITERAL1 + +VERTICAL_ALIGNMENT_TOP LITERAL1 +VERTICAL_ALIGNMENT_CENTER LITERAL1 +VERTICAL_ALIGNMENT_BOTTOM LITERAL1 + +HORIZONTAL LITERAL1 +VERTICAL LITERAL1 + +DB_TYPE_LABEL LITERAL1 +DB_TYPE_BUTTON LITERAL1 +DB_TYPE_TEXT LITERAL1 +DB_TYPE_SIGNAL LITERAL1 +DB_TYPE_RADIOGROUP LITERAL1 + +DEFAULT_UART_BAUDRATE LITERAL1 +DEFAULT_UART_TIMEOUT LITERAL1 +DEFAULT_TWI_ADDRESS LITERAL1 +DEFAULT_TWI_FREQUENCY LITERAL1 +DEFAULT_TWI_TIMEOUT LITERAL1 +DEFAULT_SPI_FREQUENCY LITERAL1 +DEFAULT_VIEW LITERAL1 \ No newline at end of file diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..14dbcdb --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=DataVisualizer +version=1.0.0 +author=Deiring Andreas +maintainer=Deiring Andreas +sentence=This library is intended to simplify the use from Microchip Data Visualizer via the Atmel Data Protocol. +paragraph=The Atmel Data Protocol is a content independent protocol intended for transferring data from a target MCU to a host PC. The connection can be established via a Serial Port or the Data Gateway Interface (EDBG-based Debugger). +category=Communication +url=https://github.com/LaCocoRoco/DataVisualizer +architectures=* \ No newline at end of file diff --git a/src/AtmelDataGateway.h b/src/AtmelDataGateway.h new file mode 100644 index 0000000..71d49c4 --- /dev/null +++ b/src/AtmelDataGateway.h @@ -0,0 +1,26 @@ +#ifndef ATMEL_DATA_GATEWAY_H +#define ATMEL_DATA_GATEWAY_H + +#ifdef __has_include + +#if __has_include() +#define GATEWAY_INCLUDED_TWI +#endif + +#if __has_include() +#define GATEWAY_INCLUDED_UART +#endif + +#if __has_include() +#define GATEWAY_INCLUDED_SPI +#endif + +#else + +#define GATEWAY_INCLUDED_UART +#define GATEWAY_INCLUDED_TWI +#define GATEWAY_INCLUDED_SPI + +#endif + +#endif \ No newline at end of file diff --git a/src/AtmelDataGatewaySpi.cpp b/src/AtmelDataGatewaySpi.cpp new file mode 100644 index 0000000..02c1a49 --- /dev/null +++ b/src/AtmelDataGatewaySpi.cpp @@ -0,0 +1,44 @@ +#include "AtmelDataGatewaySpi.h" + +#ifdef GATEWAY_INCLUDED_SPI + +void AtmelDataGatewaySpi::begin(void) { + SPISettings settings(DEFAULT_SPI_FREQUENCY, MSBFIRST, SPI_MODE0); + SPI.begin(); + this->begin(&SPI, settings, SS); +} + +void AtmelDataGatewaySpi::begin(SPIClass* spi, SPISettings settings, uint8_t ss) { + pinMode(ss, OUTPUT); + this->spi = spi; + this->ss = ss; + this->settings = settings; +} + +void AtmelDataGatewaySpi::transmit(uint8_t* txBuffer, uint16_t length) { + digitalWrite(this->ss, LOW); + this->spi->beginTransaction(this->settings); + for(uint8_t i = 0; i < length; i++) this->spi->transfer(txBuffer[i]); + this->spi->endTransaction(); + digitalWrite(this->ss, HIGH); +} + +uint16_t AtmelDataGatewaySpi::receive(uint8_t* rxBuffer, uint16_t length) { + digitalWrite(this->ss, LOW); + this->spi->beginTransaction(this->settings); + for(uint8_t i = 0; i < length; i++) rxBuffer[i] = this->spi->transfer(DEFAULT_TOKEN); + this->spi->endTransaction(); + digitalWrite(this->ss, HIGH); + return length; +} + +uint16_t AtmelDataGatewaySpi::transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length) { + digitalWrite(this->ss, LOW); + this->spi->beginTransaction(this->settings); + for(uint8_t i = 0; i < length; i++) rxBuffer[i] = this->spi->transfer(txBuffer[i]); + this->spi->endTransaction(); + digitalWrite(this->ss, HIGH); + return length; +} + +#endif \ No newline at end of file diff --git a/src/AtmelDataGatewaySpi.h b/src/AtmelDataGatewaySpi.h new file mode 100644 index 0000000..d4f2d1b --- /dev/null +++ b/src/AtmelDataGatewaySpi.h @@ -0,0 +1,33 @@ +#ifndef ATMEL_DATA_GATEWAY_INCLUDED_SPI_H +#define ATMEL_DATA_GATEWAY_INCLUDED_SPI_H + +#include "AtmelDataGateway.h" + +#ifdef GATEWAY_INCLUDED_SPI + +#include "AtmelDataProtocol.h" + +#include +#include + +#define DEFAULT_TWI_TIMEOUT 0 +#define DEFAULT_SPI_FREQUENCY 4000000 +#define DEFAULT_TOKEN ADP_TOKEN + +class AtmelDataGatewaySpi { + private: + SPIClass* spi; + SPISettings settings; + uint8_t ss; + + public: + void begin(void); + void begin(SPIClass* spi, SPISettings settings, uint8_t ss); + void transmit(uint8_t* txBuffer, uint16_t length); + uint16_t receive(uint8_t* rxBuffer, uint16_t length); + uint16_t transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length); +}; + +#endif + +#endif \ No newline at end of file diff --git a/src/AtmelDataGatewayTwi.cpp b/src/AtmelDataGatewayTwi.cpp new file mode 100644 index 0000000..4e37a58 --- /dev/null +++ b/src/AtmelDataGatewayTwi.cpp @@ -0,0 +1,36 @@ +#include "AtmelDataGatewayTwi.h" + +#ifdef GATEWAY_INCLUDED_TWI + +void AtmelDataGatewayTwi::begin(void) { + Wire.begin(); + this->begin(&Wire, DEFAULT_TWI_ADDRESS); +} + +void AtmelDataGatewayTwi::begin(TwoWire* twi, uint8_t address) { + this->address = address; + this->twi = twi; + this->twi->setTimeout(DEFAULT_TWI_TIMEOUT); +} + +void AtmelDataGatewayTwi::transmit(uint8_t* txBuffer, uint16_t length) { + this->twi->beginTransmission(this->address); + this->twi->write(txBuffer, length); + this->twi->endTransmission(); +} + +uint16_t AtmelDataGatewayTwi::receive(uint8_t* rxBuffer, uint16_t length) { + this->twi->requestFrom(this->address, length); + uint16_t rxLength = this->twi->available(); + if(!rxLength) return 0; + rxLength = rxLength > length ? length : rxLength; + this->twi->readBytes(rxBuffer, rxLength); + return rxLength; +} + +uint16_t AtmelDataGatewayTwi::transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length) { + this->transmit(txBuffer, length); + return this->receive(rxBuffer, length); +} + +#endif \ No newline at end of file diff --git a/src/AtmelDataGatewayTwi.h b/src/AtmelDataGatewayTwi.h new file mode 100644 index 0000000..adbdf80 --- /dev/null +++ b/src/AtmelDataGatewayTwi.h @@ -0,0 +1,32 @@ +#ifndef ATMEL_DATA_GATEWAY_INCLUDED_TWI_H +#define ATMEL_DATA_GATEWAY_INCLUDED_TWI_H + +#include "AtmelDataGateway.h" + +#ifdef GATEWAY_INCLUDED_TWI + +#include "AtmelDataProtocol.h" + +#include +#include + +#define DEFAULT_TWI_TIMEOUT 0 +#define DEFAULT_TWI_ADDRESS 40 +#define DEFAULT_TWI_FREQUENCY 100000 + +class AtmelDataGatewayTwi { + private: + TwoWire* twi; + uint8_t address; + + public: + void begin(void); + void begin(TwoWire* twi, uint8_t address); + void transmit(uint8_t* txBuffer, uint16_t length); + uint16_t receive(uint8_t* rxBuffer, uint16_t length); + uint16_t transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length); +}; + +#endif + +#endif \ No newline at end of file diff --git a/src/AtmelDataGatewayUart.cpp b/src/AtmelDataGatewayUart.cpp new file mode 100644 index 0000000..9fc63f3 --- /dev/null +++ b/src/AtmelDataGatewayUart.cpp @@ -0,0 +1,32 @@ +#include "AtmelDataGatewayUart.h" + +#ifdef GATEWAY_INCLUDED_UART + +void AtmelDataGatewayUart::begin(void) { + Serial.begin(DEFAULT_UART_BAUDRATE); + this->begin(&Serial); +} + +void AtmelDataGatewayUart::begin(Stream* uart) { + this->uart = uart; + this->uart->setTimeout(DEFAULT_UART_TIMEOUT); +} + +void AtmelDataGatewayUart::transmit(uint8_t* txBuffer, uint16_t length) { + this->uart->write(txBuffer, length); +} + +uint16_t AtmelDataGatewayUart::receive(uint8_t* rxBuffer, uint16_t length) { + uint16_t rxLength = this->uart->available(); + if(!rxLength) return 0; + rxLength = rxLength > length ? length : rxLength; + this->uart->readBytes(rxBuffer, rxLength); + return rxLength; +} + +uint16_t AtmelDataGatewayUart::transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length) { + this->transmit(txBuffer, length); + return this->receive(rxBuffer, length); +} + +#endif \ No newline at end of file diff --git a/src/AtmelDataGatewayUart.h b/src/AtmelDataGatewayUart.h new file mode 100644 index 0000000..ceeb9cd --- /dev/null +++ b/src/AtmelDataGatewayUart.h @@ -0,0 +1,40 @@ +#ifndef ATMEL_DATA_GATEWAY_INCLUDED_UART_H +#define ATMEL_DATA_GATEWAY_INCLUDED_UART_H + +#include "AtmelDataGateway.h" + +#ifdef GATEWAY_INCLUDED_UART + +#include "AtmelDataProtocol.h" + +#include +#include + +#define BAUDRATE_9600 9600 +#define BAUDRATE_19200 19200 +#define BAUDRATE_38400 38400 +#define BAUDRATE_57600 57600 +#define BAUDRATE_115200 115200 +#define BAUDRATE_230400 230400 +#define BAUDRATE_500000 500000 +#define BAUDRATE_1000000 1000000 +#define BAUDRATE_2000000 2000000 + +#define DEFAULT_UART_BAUDRATE BAUDRATE_230400 +#define DEFAULT_UART_TIMEOUT 0 + +class AtmelDataGatewayUart { + private: + Stream *uart; + + public: + void begin(void); + void begin(Stream* uart); + void transmit(uint8_t* txBuffer, uint16_t length); + uint16_t receive(uint8_t* rxBuffer, uint16_t length); + uint16_t transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length); +}; + +#endif + +#endif \ No newline at end of file diff --git a/src/AtmelDataProtocol.cpp b/src/AtmelDataProtocol.cpp new file mode 100644 index 0000000..c4ee968 --- /dev/null +++ b/src/AtmelDataProtocol.cpp @@ -0,0 +1,1274 @@ +#include "AtmelDataProtocol.h" + +AtmelDataProtocol::AtmelDataProtocol(void) { + this->lastReceivedMessageId = ADP_TOKEN; + this->packetReceived = false; + this->prevData = 0; +} + +void AtmelDataProtocol::addAtmelDataGateway(AtmelDataGateway* gateway) { + this->gateway = gateway; +} + +void AtmelDataProtocol::setColor(uint8_t *structMember, RgbColor color) { + structMember[0] = color.red; + structMember[1] = color.green; + structMember[2] = color.blue; +} + +void AtmelDataProtocol::configureStreamGetDefaults(MsgConfigStream *const config) { + config->streamId = 0; + config->type = STREAM_UINT_8; + config->mode = STREAM_OUT; + config->state = STREAM_ON; +} + +void AtmelDataProtocol::configureGraphGetDefaults(MsgConfigGraph *const config) { + config->graphId = 0; + config->xMin = 0; + config->xMax = 0; + config->xScaleNumerator = 0; + config->xScaleDenominator = 0; + /* Bug: Auto scaling results in bouncing y scale */ + config->scaleMode = GRAPH_SCALE_OFF; + /* Bug: Scroll by time not working */ + config->scrollMode = GRAPH_SCROLL_SCROLL; + setColor(config->backgroundColor, COLOR_BLACK); +} + +void AtmelDataProtocol::addAxisToGraphGetDefaults(MsgConfigAxis *const config) { + config->axisId = 0; + config->graphId = 0; + config->yMin = 0; + config->yMax = 0; + config->xScaleNumerator = 0; + config->xScaleDenominator = 0; + config->mode = 0; + setColor(config->color, COLOR_BLACK); +} + +void AtmelDataProtocol::addStreamToAxisGetDefaults(MsgAddStreamToAxis *const config) { + config->graphId = 0; + config->axisId = 0; + config->streamId = 0; + config->sampleRateNumerator = 0; + config->sampleRateDenominator = 0; + config->yScaleNumerator = 0; + config->yScaleDenominator = 0; + config->yOffset = 0; + config->transparency = 0; + config->mode = AXIS_LINE_bm; + config->lineThickness = 1; + setColor(config->lineColor, COLOR_BLACK); +} + +void AtmelDataProtocol::addCursorToGraphGetDefaults(MsgAddCursorToGraph *const config) { + config->streamId = 0; + config->graphId = 0; + config->axisId = 0; + config->thickness = 1; + config->initialValue = 0; + config->minimumValue = 0; + config->maximumValue = 0; + config->scaleNumerator = 0; + config->scaleDenominator = 0; + config->scaleOffset = 0; + config->lineStyle = 0; + setColor(config->color, COLOR_WHITE); +} + +void AtmelDataProtocol::addGpioToGraphGetDefaults(MsgConfigGpioToGraph *const config) { + config->graphId = 0; + config->gpioNumber = 0; + config->groupId = 0; + config->transparency = 0; + config->mode = 0; + config->lineThickness = 1; + config->lineStyle = 0; + setColor(config->lineColorHighState, COLOR_WHITE); + setColor(config->lineColorLowState, COLOR_WHITE); +} + +void AtmelDataProtocol::configureTerminalGetDefaults(MsgConfigTerminal *const config) { + config->terminalId = 0; + config->width = 80; + config->height = 25; + setColor(config->backgroundColor, COLOR_WHITE); + setColor(config->foregroundColor, COLOR_BLACK); +} + +void AtmelDataProtocol::addStreamToTerminalGetDefaults(MsgConfigAddStreamToTerminal *const config) { + config->terminalId = 0; + config->streamId = 0; + config->mode = 0; + setColor(config->textColor, COLOR_BLACK); + setColor(config->tagTextColor, COLOR_BLACK); +} + +void AtmelDataProtocol::configureDashboardGetDefaults(MsgConfigDahsboard *const config) { + config->dashboardId = 0; + config->height = 100; + setColor(config->color, COLOR_BLACK); +} + +void AtmelDataProtocol::configureDashboardElementGetDefaults(MsgConfigDashboardElementCommon *const config) { + config->dashboardId = 0; + config->elementId = 0; + config->zIndex = 0; + config->x = 0; + config->y = 0; + config->width = 0; + config->height = 0; +} + +void AtmelDataProtocol::configureDashboardLabelGetDefaults(MsgConfigDashboardElementLabel *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_LABEL; + config->fontSize = 10; + config->attribute = 0; + config->horisontalAlignment = HORISONTAL_ALIGNMENT_LEFT; + config->verticalAlignment = VERTICAL_ALIGNMENT_CENTER; + config->backgroundTransparency = 0; + config->foregroundTransparency = 0; + setColor(config->backgroundColor, COLOR_BLACK); + setColor(config->foregroundColor, COLOR_BLACK); +} + +void AtmelDataProtocol::configureDashboardButtonGetDefaults(MsgConfigDashboardElementButton *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_BUTTON; + config->fontSize = 10; + config->toggle = 0; +} + +void AtmelDataProtocol::configureDashboardTextGetDefaults(MsgConfigDashboardElementText *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_TEXT; + memset(config->minimum, 0, 4); + memset(config->maximum, 0, 4); + memset(config->value, 0, 4); +} + +void AtmelDataProtocol::configureDashboardSliderGetDefaults(MsgConfigDashboardElementSlider *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_SLIDER; + config->minimumValue = 0; + config->maximumValue = 100; + config->initialValue = 0; +} + +void AtmelDataProtocol::configureDashboardSignalGetDefaults(MsgConfigDashboardElementSignal *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_SIGNAL; + config->onTransparency = 0; + config->offTransparency = 0; + setColor(config->onColor, COLOR_WHITE); + setColor(config->offColor, COLOR_BLACK); +} + +void AtmelDataProtocol::configureDashboardPrograssGetDefaults(MsgConfigDashboardElementProgress *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elemntType = ELEMENT_TYPE_PROGRESS; + config->minimumValue = 0; + config->maximumValue = 100; + config->initialValue = 0; + setColor(config->color, COLOR_BLACK); +} + +void AtmelDataProtocol::configureDashboardSegmentGetDefaults(MsgConfigDashboardElementSegment *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_SEGMENT; + config->segmentCount = 1; + config->base = 10; + config->transparency = 0; + setColor(config->color, COLOR_BLACK); +} + +void AtmelDataProtocol::configureDashboardGraphGetDefaults(MsgConfigDashboardElementGraph *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_GRAPH; + config->plotCount = 1; + config->xMin = 0; + config->xMax = 10; + config->yMin = 0; + config->yMax = 5; + config->mode.bit.autoscale = 0; + config->mode.bit.fitGraph = 1; + config->mode.bit.mouse = 0; + config->mode.bit.scrollByTime = 0; + config->mode.bit.showPlot = 0; + config->mode.bit.showPoints = 0; + setColor(config->titleColor, COLOR_WHITE); + setColor(config->backgroundColor, COLOR_BLACK); + setColor(config->graphBackgroundColor, COLOR_BLACK); +} + +void AtmelDataProtocol::configureDashboardRadioGetDefaults(MsgConfigDashboardElementRadio *const config) { + configureDashboardElementGetDefaults((MsgConfigDashboardElementCommon *)config); + config->elementType = ELEMENT_TYPE_RADIO; + config->fontSize = 10; + config->numberItems = 1; + config->orientation = HORIZONTAL; +} + +uint16_t AtmelDataProtocol::addSendByte(uint8_t *buffer, uint8_t index, uint8_t *data, uint16_t length) { + for(uint16_t i = 0; i < length; i++) { + if(*(data + i) == ADP_TOKEN) { + *(buffer + index) = ADP_TOKEN; + index++; + } + *(buffer + index) = *(data + i); + index++; + } + + return index; +} + +bool AtmelDataProtocol::addReceiveByte(uint8_t data) { + static uint8_t messageId; + + if((rxState == RX_STATE_GOT_SYMBOL) && (data != ADP_TOKEN)) { + /* Abort packet reception, new packet incoming */ + rxState = RX_STATE_WAIT_LENGTH_LSB; + } + + switch(rxState) { + case RX_STATE_IDLE: + packetReceived = false; + lastReceivedMessageId = 0xFF; + /* We are waiting for a new packet. */ + if(data != ADP_TOKEN) { + return false; + } + /* Got start symbol, wait for message ID */ + rxState = RX_STATE_WAIT_MSG_ID; + return false; + + case RX_STATE_WAIT_MSG_ID: + if(data == ADP_TOKEN) { + /* Restart. Don't change state. Wait for new message ID */ + return false; + } + messageId = data; + rxState = RX_STATE_WAIT_LENGTH_LSB; + return false; + + case RX_STATE_WAIT_LENGTH_LSB: + if(data == ADP_TOKEN) { + if(prevData != ADP_TOKEN) { + prevData = ADP_TOKEN; + return false; + } + } + lengthReceived = data; + rxState = RX_STATE_WAIT_LENGTH_MSB; + prevData = 0; + return false; + + case RX_STATE_WAIT_LENGTH_MSB: + if(data == ADP_TOKEN) { + if(prevData != ADP_TOKEN) { + prevData = ADP_TOKEN; + return false; + } + } + lengthReceived += (uint16_t)data << 8; + prevData = 0; + /* Got valid length, do we expect data? */ + if(lengthReceived == 0) { + /* No data here, wait for next packet */ + rxState = RX_STATE_IDLE; + packetReceived = true; + lastReceivedMessageId = messageId; + return false; + } + + /* Wait for packet data */ + bytesReceived = 0; + rxState = RX_STATE_GET_DATA; + return false; + + case RX_STATE_GET_DATA: + case RX_STATE_GOT_SYMBOL: + if((data == ADP_TOKEN) && (rxState == RX_STATE_GET_DATA)) { + rxState = RX_STATE_GOT_SYMBOL; + return false; + } + /* Add new data to rx buffer */ + bytesReceived++; + /* Are we done yet? */ + + if(bytesReceived >= lengthReceived || lengthReceived > MSG_RES_DATA_MAX_LEN) { + /* Yes we are! */ + packetReceived = true; + rxState = RX_STATE_IDLE; + lastReceivedMessageId = messageId; + return true; + } + /* Not done yet.. keep on receiving */ + rxState = RX_STATE_GET_DATA; + return true; + } + return false; +} + +bool AtmelDataProtocol::isReceived(void) { + if(bytesReceived == 0) { + return false; + } + return packetReceived; +} + +uint8_t AtmelDataProtocol::packetReceiveGetId(void) { + return lastReceivedMessageId; +} + +bool AtmelDataProtocol::protocolAddByte(uint8_t rxId, uint8_t *rxBuffer, uint16_t rxLength, uint8_t *rxPacket, uint16_t rxPacketLength) { + uint8_t i; + + for(i = 0; i < rxLength; i++) { + if(addReceiveByte(*(rxBuffer + i)) == true) { + /* This is a data byte */ + rxPacketBuffer[bytesReceived - 1] = *(rxBuffer + i); + } + + if(isReceived() && (packetReceiveGetId() == rxId)) { + memcpy(rxPacket, rxPacketBuffer, rxPacketLength); + memset(rxPacketBuffer, 0, MSG_RES_DATA_PACKET_MAX_LEN); + + return true; + } + } + + return false; +} + +bool AtmelDataProtocol::checkForResponse(uint8_t rxId, uint8_t *rxPacket, uint16_t rxPacketLength) { + uint16_t txLength = rxPacketLength + ADP_LENGTH_PACKET_HEADER; + uint8_t retry = ADP_CHECK_FOR_RESPONSE_RETRYS; + + uint8_t rxBuffer[txLength]; + memset(rxBuffer, 0, txLength); + + rxState = RX_STATE_IDLE; + packetReceived = false; + memset(rxPacketBuffer, 0, MSG_RES_DATA_PACKET_MAX_LEN); + + while(!isReceived() & (retry-- > 0)) { + uint16_t rxLength = this->gateway->receive(rxBuffer, txLength); + if(protocolAddByte(rxId, rxBuffer, rxLength, rxPacket, rxPacketLength)) return true; + } + + return false; +} + +void AtmelDataProtocol::waitForResponse(uint8_t rxId, uint8_t *rxPacket, uint16_t rxPacketLength) { + uint16_t txLength = rxPacketLength + ADP_LENGTH_PACKET_HEADER; + + uint8_t rxBuffer[txLength]; + memset(rxBuffer, 0, txLength); + + rxState = RX_STATE_IDLE; + packetReceived = false; + memset(rxPacketBuffer, 0, MSG_RES_DATA_PACKET_MAX_LEN); + + while(!isReceived()) { + uint16_t rxLength = this->gateway->receive(rxBuffer, txLength); + protocolAddByte(rxId, rxBuffer, rxLength, rxPacket, rxPacketLength); + } +} + +bool AtmelDataProtocol::requestHandshake(uint8_t protocolVersion, uint8_t options, uint8_t *rxPacket) { + uint16_t txLength = MSQ_REQ_HANDSHAKE_LEN + ADP_LENGTH_PACKET_HEADER; + uint8_t key[8] = ADP_HANDSHAKE_KEY; + + MsgFormat msgFormat; + MsgRequestHandshake msgRequestHandshake; + + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_REQ_HANDSHAKE; + msgFormat.dataLength = MSQ_REQ_HANDSHAKE_LEN; + + msgRequestHandshake.protocolVersion = ADP_VERSION; + msgRequestHandshake.options = HANDSHAKE_OPTIONS_GPIO; + + memcpy(&msgRequestHandshake.key, key, 8); + memcpy((uint8_t *)&msgFormat.data, &msgRequestHandshake, sizeof(msgRequestHandshake)); + + /* Send the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_RES_HANDSHAKE; + uint16_t rxPacketLength = 1; + + return checkForResponse(rxId, rxPacket, rxPacketLength); +} + +HandshakeStatus AtmelDataProtocol::waitForHandshake(void) { + uint8_t handshake_status; + + /* Keep sending handshake until we get something back */ + while(!requestHandshake(ADP_VERSION, 0, &handshake_status)); + + /* Return status */ + return ((HandshakeStatus)handshake_status); +} + +StatusCode AtmelDataProtocol::requestStatus(void) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_REQ_STATUS; + msgFormat.dataLength = MSG_REQ_STATUS_LEN; + + uint16_t tx_length = MSG_REQ_STATUS_LEN + ADP_LENGTH_PACKET_HEADER; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, tx_length); + + uint8_t rxId = MSG_RES_STATUS; + uint16_t rxPacket; + uint16_t rxPacketLength = 2; + + /* Wait for response from PC */ + waitForResponse(rxId, (uint8_t *)&rxPacket, rxPacketLength); + + return ((StatusCode)rxPacket); +} + +uint16_t AtmelDataProtocol::verifyDataLength(uint16_t length) { + return length <= ADP_MAX_PROTOCOL_LEN ? length : ADP_MAX_PROTOCOL_LEN; +} + +bool AtmelDataProtocol::configureInfo(const char *title, const char *description) { + /* Add null-termination to length */ + uint16_t titleLength = strlen(title) + 1; + uint16_t descriptionLength = strlen(description) + 1; + + /* Make sure the strings are not too long */ + uint16_t dataLength = verifyDataLength(MSG_CONF_INFO_LEN + titleLength + descriptionLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_INFO; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)title, titleLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)description, descriptionLength); + + uint16_t tx_length = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, tx_length); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::configureStream(MsgConfigStream *const config, const char *label) { + /* Add null-termination to length */ + uint16_t labelLength = strlen(label) + 1; + + /* Make sure the strings are not too long */ + uint16_t dataLength = verifyDataLength(MSG_CONF_STREAM_LEN + labelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_STREAM; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->streamId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->type, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->mode, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->state, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)label, labelLength); + + uint16_t tx_length = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, tx_length); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::toggleStream(MsgToggleStream *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_TOGGLE_STREAM; + msgFormat.dataLength = MSG_CONF_TOGGLE_STREAM_LEN; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->streamId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->state, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + + +bool AtmelDataProtocol::configureGraph(MsgConfigGraph *const config, const char *graphLabel, const char *xLabel) { + /* Add 0-termination to label string length */ + uint16_t graphLabelLength = strlen(graphLabel) + 1; + uint16_t xLabelLength = strlen(xLabel) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(MSG_CONF_GRAPH_LEN + graphLabelLength + xLabelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_GRAPH; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->graphId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)graphLabel, graphLabelLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xMin, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xMax, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)xLabel, xLabelLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xScaleNumerator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xScaleDenominator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->scaleMode, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->backgroundColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->scrollMode, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::configureTerminal(MsgConfigTerminal *const config, const char *label) { + /* Add 0-termination to label string length */ + uint16_t labelLength = strlen(label) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(MSG_CONF_TERMINAL_LEN + labelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_TERMINAL; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->terminalId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)label, labelLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->width, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->height, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->backgroundColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->foregroundColor, 3); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addStreamToTerminal(MsgConfigAddStreamToTerminal *const config, const char *tagText) { + /* Add 0-termination to label string length */ + uint16_t tagTextLength = strlen(tagText) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(MSG_CONF_ADD_TO_TERMINAL_LEN + tagTextLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_ADD_TO_TERMINAL; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->terminalId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->streamId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->mode, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->textColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)tagText, tagTextLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->tagTextColor, 3); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addAxisToGraph(MsgConfigAxis *const config, const char *label) { + /* Add 0-termination to label string length */ + uint16_t labelLength = strlen(label) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(MSG_CONF_AXIS_LEN + labelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_AXIS; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->axisId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->graphId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)label, labelLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->yMin, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->yMax, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xScaleNumerator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xScaleDenominator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->mode, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->color, 3); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addStreamToAxis(MsgAddStreamToAxis *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_ADD_STREAM_TO_AXIS; + msgFormat.dataLength = MSG_CONF_ADD_STREAM_TO_AXIS_LEN; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->axisId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->graphId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->streamId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->sampleRateNumerator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->sampleRateDenominator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->yScaleNumerator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->yScaleDenominator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->yOffset, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->transparency, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->mode, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->lineThickness, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->lineColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)ADP_BUG_FIX, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addCursorToGraph(MsgAddCursorToGraph *const config, const char *label) { + /* Add 0-termination to label string length */ + uint16_t labelLength = strlen(label) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(MSG_CONF_CURSOR_TO_GRAPH_LEN + labelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_CURSOR_TO_GRAPH; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->streamId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->axisId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->graphId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)label, labelLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->thickness, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->color, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->initialValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->minimumValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->maximumValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->scaleNumerator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->scaleDenominator, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->scaleOffset, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->lineStyle, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addGpioToGraph(MsgConfigGpioToGraph *const config, const char *tagHighState, const char *tagLowState) { + /* Add 0-termination to label string length */ + uint16_t tagHighStateLength = strlen(tagHighState) + 1; + uint16_t tagLowStateLength = strlen(tagLowState) + 1; + uint16_t labelLength = tagHighStateLength + tagLowStateLength; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(MSG_CONF_GPIO_TO_GRAPH_LEN + labelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_GPIO_TO_GRAPH; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->graphId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->gpioNumber, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->graphId, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)tagHighState, tagHighStateLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)tagLowState, tagLowStateLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->transparency, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->mode, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->lineThickness, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->lineColorHighState, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->lineColorLowState, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->lineStyle, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addDashboard(MsgConfigDahsboard *const config, const char *label) { + /* Add 0-termination to label string length */ + uint16_t labelLength = strlen(label) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(MSG_CONF_DASHBOARD_LEN + labelLength); + + MsgFormat msgFormat; + + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->dashboardId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)label, labelLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->color, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->height, 2); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +uint16_t AtmelDataProtocol::addSendByteDashboard(uint8_t *addBuffer, uint16_t index, MsgConfigDashboardElementCommon *const config) { + index = addSendByte(addBuffer, index, (uint8_t *)&config->dashboardId, 2); + index = addSendByte(addBuffer, index, (uint8_t *)&config->elementId, 2); + index = addSendByte(addBuffer, index, (uint8_t *)&config->zIndex, 1); + index = addSendByte(addBuffer, index, (uint8_t *)&config->x, 2); + index = addSendByte(addBuffer, index, (uint8_t *)&config->y, 2); + index = addSendByte(addBuffer, index, (uint8_t *)&config->width, 2); + index = addSendByte(addBuffer, index, (uint8_t *)&config->height, 2); + index = addSendByte(addBuffer, index, (uint8_t *)&config->elementType, 1); + + return index; +} + +bool AtmelDataProtocol::addLabelToDashboard(MsgConfigDashboardElementLabel *const config, const char *label) { + /* Add 0-termination to label string length */ + uint16_t labelLength = strlen(label) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(ELEMENT_TYPE_LABEL_LEN + labelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->fontSize, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->attribute, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->horisontalAlignment, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->verticalAlignment, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->backgroundTransparency, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->backgroundColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->foregroundTransparency, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->foregroundColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)label, labelLength); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addButtonToDashboard(MsgConfigDashboardElementButton *const config, const char *label) { + /* Add 0-termination to label string length */ + uint16_t labelLength = strlen(label) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(ELEMENT_TYPE_BUTTON_LEN + labelLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->fontSize, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)label, labelLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->toggle, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Send the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addSliderToDashboard(MsgConfigDashboardElementSlider *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = ELEMENT_TYPE_SLIDER_LEN; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->minimumValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->maximumValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->initialValue, 4); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addProgressToDashboard(MsgConfigDashboardElementProgress *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = ELEMENT_TYPE_PROGRESS_LEN; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->minimumValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->maximumValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->initialValue, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->color, 3); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Send the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addSignalToDashboard(MsgConfigDashboardElementSignal *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = ELEMENT_TYPE_SIGNAL_LEN; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->onTransparency, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->onColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->offTransparency, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->offColor, 3); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addSegmentToDashboard(MsgConfigDashboardElementSegment *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = ELEMENT_TYPE_SEGMENT_LEN; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->segmentCount, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->base, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->transparency, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->color, 3); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addGraphToDashboard(MsgConfigDashboardElementGraph *const config, const char *title) { + /* Add 0-termination to label string length */ + uint16_t titleLength = strlen(title) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(ELEMENT_TYPE_GRAPH_LEN + titleLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->titleColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->backgroundColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->graphBackgroundColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)title, titleLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->plotCount, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xMin, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->xMax, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->yMin, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->yMax, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->mode, 2); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addTextToDashboard(MsgConfigDashboardElementText *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = ELEMENT_TYPE_TEXT_LEN; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->minimum, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->maximum, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->value, 4); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)ADP_BUG_FIX, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addRadioToDashboard(MsgConfigDashboardElementRadio *const config, const char *text) { + /* Add 0-termination to label string length */ + uint16_t textLength = strlen(text) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(ELEMENT_TYPE_RADIO_LEN + textLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->fontSize, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->numberItems, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->orientation, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)text, textLength); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addPieToDashboard(MsgConfigDashboardElementPie *const config, const char *title) { + /* Add 0-termination to label string length */ + uint16_t titleLength = strlen(title) + 1; + + /* Make sure label isn't too big */ + uint16_t dataLength = verifyDataLength(ELEMENT_TYPE_PIE_LEN + titleLength); + + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_DASHBOARD_ELEMENT; + msgFormat.dataLength = dataLength; + + uint16_t index = 0; + + index = addSendByteDashboard((uint8_t *)&msgFormat.data, index, (MsgConfigDashboardElementCommon *)config); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->backgroundColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->titleColor, 3); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)title, titleLength); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->numberSlices, 1); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::addStreamToElement(MsgConfigAddStreamToElement *const config) { + MsgFormat msgFormat; + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_CONF_ADD_STREAM_TO_ELEMENT; + msgFormat.dataLength = MSG_CONF_ADD_STREAM_TO_ELEMENT_LEN; + + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->dashboardId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->elementId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&config->streamId, 2); + + uint16_t txLength = ADP_LENGTH_PACKET_HEADER + index; + + /* Transmit the protocol packet data */ + this->gateway->transmit((uint8_t *)&msgFormat, txLength); + + uint8_t rxId = MSG_CONF_ACK; + uint8_t rxPacket; + uint16_t rxPacketLength = 1; + + /* Wait for response and return status */ + waitForResponse(rxId, &rxPacket, rxPacketLength); + + return (rxPacket == ACK_OK); +} + +bool AtmelDataProtocol::transceiveStream(MsgDataStream *const streamData, uint8_t *rxPacket) { + MsgFormat msgFormat; + + uint16_t dataLength = 1; + uint16_t index = 0; + + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&streamData->numberOfStreams, 1); + + for(uint8_t stream_num = 0; stream_num < streamData->numberOfStreams; stream_num++) { + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&streamData->stream[stream_num].streamId, 2); + index = addSendByte((uint8_t *)&msgFormat.data, index, (uint8_t *)&streamData->stream[stream_num].dataSize, 1); + index = addSendByte((uint8_t *)&msgFormat.data, index, streamData->stream[stream_num].data, streamData->stream[stream_num].dataSize); + /* 2 bytes stream.stream_id and 1 byte stream.data_size */ + dataLength += 2 + 1 + streamData->stream[stream_num].dataSize; + } + + msgFormat.protocolToken = ADP_TOKEN; + msgFormat.protocolMsgId = MSG_DATA_STREAM; + msgFormat.dataLength = dataLength; + + uint16_t txrxLength = ADP_LENGTH_PACKET_HEADER + index; + uint16_t rxPacketLength = MSG_RES_DATA_PACKET_MAX_LEN; + uint8_t rxId = MSG_RES_DATA; + + uint8_t rxBuffer[txrxLength]; + memset(rxBuffer, 0, txrxLength); + + /* Transmit and receive protocol packet data */ + uint16_t rxLength = this->gateway->transceive((uint8_t *)&msgFormat, rxBuffer, txrxLength); + + return protocolAddByte(rxId, rxBuffer, rxLength, rxPacket, rxPacketLength); +} + +bool AtmelDataProtocol::transceiveSingleStream(uint16_t streamId, uint8_t *data, uint8_t dataSize, uint8_t *rxPacket) { + MsgDataStream msgDataStream; + + msgDataStream.numberOfStreams = 1; + msgDataStream.stream[0].streamId = streamId; + msgDataStream.stream[0].dataSize = dataSize; + msgDataStream.stream[0].data = data; + + uint8_t status = transceiveStream(&msgDataStream, rxPacket); + + return status; +} + +bool AtmelDataProtocol::receivePacketData(uint8_t *rxPacket) { + uint16_t rxPacketLength = MSG_RES_DATA_PACKET_MAX_LEN; + uint8_t txrxLength = MSG_RES_DATA_REQUEST; + uint8_t rxId = MSG_RES_DATA; + + uint8_t rxBuffer[txrxLength]; + memset(rxBuffer, 0, txrxLength); + + /* Transmit and receive protocol packet data */ + uint16_t rxLength = this->gateway->receive(rxBuffer, txrxLength); + + return protocolAddByte(rxId, rxBuffer, rxLength, rxPacket, rxPacketLength); +} \ No newline at end of file diff --git a/src/AtmelDataProtocol.h b/src/AtmelDataProtocol.h new file mode 100644 index 0000000..19bbdb4 --- /dev/null +++ b/src/AtmelDataProtocol.h @@ -0,0 +1,771 @@ +#ifndef ATMEL_DATA_PROTOCOL_H +#define ATMEL_DATA_PROTOCOL_H + +#include +#include +#include + +/** Bug Fix for last message byte ADP Token */ +#define ADP_BUG_FIX 0x00 + +/** Version of ADP implemented here */ +#define ADP_VERSION 1 + +/** Start token for ADP data */ +#define ADP_TOKEN 0xFF + +/** Maximum number of streams from PC to target */ +#define ADP_MAX_INCOMMING_STREAMS 5 + +/** Maximum number of streams from target to PC */ +#define ADP_MAX_OUTGOING_STREAMS 5 + +/** Key used to identify proper handshake message */ +#define ADP_HANDSHAKE_KEY {0x58, 0x99, 0xAB, 0xC9, 0x0F, 0xE2, 0xF7, 0xAA} + +/** Maximum retry for handshake request */ +#define ADP_CHECK_FOR_RESPONSE_RETRYS 50 + +/** Length of ADP packet header: Token, Message ID, Data Length */ +#define ADP_LENGTH_PACKET_HEADER 4 + +/** Maximum number of bytes in data part of ADP packet out */ +#define ADP_MAX_PROTOCOL_LEN 250 + +/** Max length of labels */ +#define ADP_CONF_MAX_LABEL 20 + +/** ADP RGB color definitions. Other RGB values can be used as well */ +#define COLOR_WHITE (RgbColor) {0xFF, 0xFF, 0xFF} +#define COLOR_BLACK (RgbColor) {0x00, 0x00, 0x00} +#define COLOR_SILVER (RgbColor) {0xC0, 0xC0, 0xC0} +#define COLOR_GRAY (RgbColor) {0x80, 0x80, 0x80} +#define COLOR_MAROON (RgbColor) {0x80, 0x00, 0x00} +#define COLOR_RED (RgbColor) {0xFF, 0x00, 0x00} +#define COLOR_PURPLE (RgbColor) {0x80, 0x00, 0x80} +#define COLOR_FUCHSIA (RgbColor) {0xFF, 0x00, 0xFF} +#define COLOR_GREEN (RgbColor) {0x00, 0x80, 0x00} +#define COLOR_LIME (RgbColor) {0x00, 0xFF, 0x00} +#define COLOR_OLIVE (RgbColor) {0x80, 0x80, 0x00} +#define COLOR_YELLOW (RgbColor) {0xFF, 0xFF, 0x00} +#define COLOR_NAVY (RgbColor) {0x00, 0x00, 0x80} +#define COLOR_BLUE (RgbColor) {0x00, 0x00, 0xFF} +#define COLOR_TEAL (RgbColor) {0x00, 0x80, 0x80} +#define COLOR_AQUA (RgbColor) {0x00, 0xFF, 0xFF} +#define COLOR_ORANGE (RgbColor) {0xFF, 0xA5, 0x00} + +#define ACK_NOT_OK 0 +#define ACK_OK 1 + +#define AXIS_LINE_bm 0x01 +#define AXIS_POINTS_bm 0x02 + +#define MSG_DATA_STREAM 0x40 + +#define MSG_REQ_HANDSHAKE 0x00 +#define MSQ_REQ_HANDSHAKE_LEN 10 + +#define MSG_REQ_STATUS 0x02 +#define MSG_REQ_STATUS_LEN 0 + +#define MSG_RES_HANDSHAKE 0x10 +#define MSG_RES_STATUS 0x12 +#define MSG_RES_DATA 0x14 +#define MSG_RES_DATA_REQUEST 10 +#define MSG_RES_DATA_PACKET_MAX_LEN 250 +#define MSG_RES_DATA_MAX_LEN MSG_RES_DATA_PACKET_MAX_LEN - 3 + +#define MSG_CONF_ACK 0x30 + +#define MSG_CONF_INFO 0x28 +#define MSG_CONF_INFO_LEN 0 + +#define MSG_CONF_STREAM 0x20 +#define MSG_CONF_STREAM_LEN 5 + +#define MSG_CONF_TOGGLE_STREAM 0x21 +#define MSG_CONF_TOGGLE_STREAM_LEN 3 + +#define MSG_CONF_GRAPH 0x22 +#define MSG_CONF_GRAPH_LEN 23 + +#define MSG_CONF_AXIS 0x29 +#define MSG_CONF_AXIS_LEN 24 + +#define MSG_CONF_ADD_STREAM_TO_AXIS 0x23 +#define MSG_CONF_ADD_STREAM_TO_AXIS_LEN 32 + +#define MSG_CONF_CURSOR_TO_GRAPH 0x24 +#define MSG_CONF_CURSOR_TO_GRAPH_LEN 35 + +#define MSG_CONF_GPIO_TO_GRAPH 0x25 +#define MSG_CONF_GPIO_TO_GRAPH_LEN 15 + +#define MSG_CONF_TERMINAL 0x26 +#define MSG_CONF_TERMINAL_LEN 10 + +#define MSG_CONF_ADD_TO_TERMINAL 0x27 +#define MSG_CONF_ADD_TO_TERMINAL_LEN 11 + +#define MSG_CONF_DASHBOARD 0x2A +#define MSG_CONF_DASHBOARD_LEN 7 + +#define MSG_CONF_DASHBOARD_ELEMENT 0x2B +#define MSG_CONF_DASHBOARD_COMMON_LEN 14 + +#define MSG_CONF_ADD_STREAM_TO_ELEMENT 0x2C +#define MSG_CONF_ADD_STREAM_TO_ELEMENT_LEN 6 + +#define ELEMENT_TYPE_LABEL_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 12) +#define ELEMENT_TYPE_BUTTON_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 2) +#define ELEMENT_TYPE_SLIDER_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 12) +#define ELEMENT_TYPE_SIGNAL_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 8) +#define ELEMENT_TYPE_PROGRESS_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 15) +#define ELEMENT_TYPE_TEXT_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 12) +#define ELEMENT_TYPE_RADIO_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 3) +#define ELEMENT_TYPE_PIE_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 7) +#define ELEMENT_TYPE_SEGMENT_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 6) +#define ELEMENT_TYPE_GRAPH_LEN (MSG_CONF_DASHBOARD_COMMON_LEN + 28) + +/** States in receive state machine */ +enum RxState { + /** We are idle, waiting for a new packet */ + RX_STATE_IDLE, + /** Start symbol received, waiting for Message ID */ + RX_STATE_WAIT_MSG_ID, + /** Message ID received, waiting for data length */ + RX_STATE_WAIT_LENGTH_LSB, + /** Message ID received, waiting for data length */ + RX_STATE_WAIT_LENGTH_MSB, + /** Length received; we are receiving packet data */ + RX_STATE_GET_DATA, + /** Start symbol received */ + RX_STATE_GOT_SYMBOL, +}; + +enum HandshakeOptions { + /* Use GPIO */ + HANDSHAKE_OPTIONS_GPIO, + /* Lock configuration */ + HANDSHAKE_OPTIONS_LOCK, +}; + +enum HandshakeStatus { + /* Handshake accepted */ + HANDSHAKE_ACCEPTED, + /* Handshake rejected. Invalid protocol version */ + HANDSHAKE_REJECTED_PROTOCOL, + /* Handshake rejected. Other reason */ + HANDSHAKE_REJECTED_OTHER, +}; + +enum StatusCode { + /* Invalid packet received */ + STATUS_INVALID_PACKET, + /* Invalid configuration data received */ + STATUS_INVALID_CONFIGURATION, + /* Data ready to be transmitted to target */ + STATUS_DATA_READY, + /* Invalid stream request (req_data) */ + STATUS_INVALID_REQUEST, + /* No data available on stream (req_data) */ + STATUS_NO_DATA, + /* Request target software reset */ + STATUS_RESET, +}; + +enum StreamType { + STREAM_EVENT, + STREAM_STRING, + STREAM_UINT_8, + STREAM_INT_8, + STREAM_UINT_16, + STREAM_INT_16, + STREAM_UINT_32, + STREAM_INT_32, + STREAM_XY_8, + STREAM_XY_16, + STREAM_XY_32, + STREAM_BOOL, + STREAM_FLOAT, +}; + +enum StreamState { + STREAM_OFF, + STREAM_ON, +}; + +enum StreaMode { + /* Incoming (normal) */ + STREAM_IN, + /* Incoming (single value) */ + STREAM_IN_SINGLE, + /* Outgoing */ + STREAM_OUT, +}; + +enum GraphScaleMode { + GRAPH_SCALE_OFF, + GRAPH_SCALE_AUTO +}; + +enum GraphScrollMode { + /* No scrolling */ + GRAPH_SCROLL_OFF, + /* Stepping */ + GRAPH_SCROLL_STEP, + /* Scroll */ + GRAPH_SCROLL_SCROLL, + /* Circular/sweep */ + GRAPH_SCROLL_CIRCULAR +}; + +enum DashboardElementType { + ELEMENT_TYPE_LABEL, + ELEMENT_TYPE_BUTTON, + ELEMENT_TYPE_SLIDER, + ELEMENT_TYPE_PROGRESS, + ELEMENT_TYPE_SIGNAL, + ELEMENT_TYPE_SEGMENT, + ELEMENT_TYPE_GRAPH, + ELEMENT_TYPE_TEXT, + ELEMENT_TYPE_RADIO, + ELEMENT_TYPE_PIE, +}; + +enum LabelAttribute { + BOLD_OFF_ITALIC_OFF, + BOLD_ON_ITALIC_OFF, + BOLD_OFF_ITALIC_ON, + BOLD_ON_ITALIC_ON, +}; + +enum LabelAligmentHorisontal { + HORISONTAL_ALIGNMENT_LEFT, + HORISONTAL_ALIGNMENT_CENTER, + HORISONTAL_ALIGNMENT_RIGHT, +}; + +enum LabelAligmentVertical { + VERTICAL_ALIGNMENT_TOP, + VERTICAL_ALIGNMENT_CENTER, + VERTICAL_ALIGNMENT_BOTTOM, +}; + +enum RadioOrientation { + HORIZONTAL, + VERTICAL, +}; + +struct RgbColor { + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +struct MsgFormat { + /* Start token for ADP data */ + uint8_t protocolToken; + /* Describes what data is sent */ + uint8_t protocolMsgId; + /* Length of data packet */ + uint16_t dataLength; + /* Data packet for the message */ + uint8_t data[ADP_MAX_PROTOCOL_LEN]; +}; + +struct MsgRequestHandshake { + /* Version of protocol on target */ + uint8_t protocolVersion; + /* Is GPIO in use in this app? + * Can user change configuration on PC side? + */ + uint8_t options; + /* Token used to verify ADP protocol */ + uint8_t key[8]; +}; + +struct MsgResponseHandshake { + enum HandshakeStatus status; +}; + +struct MsgResponseStatus { + enum StatusCode status; +}; + +struct MsgPacketData { + uint16_t streamId; + uint8_t bytesSent; + uint8_t data[MSG_RES_DATA_MAX_LEN]; +}; + +struct MsgConfigStream { + /* ID of stream */ + uint16_t streamId; + /* Stream type */ + enum StreamType type; + /* Stream mode/direction */ + enum StreaMode mode; + /* Stream state */ + enum StreamState state; +}; + +struct MsgToggleStream { + uint16_t streamId; + enum StreamState state; +}; + +struct MsgConfigGraph { + /* ID of new graph */ + uint8_t graphId; + /* Range Xmin value */ + uint32_t xMin; + /* Range Xmax value */ + uint32_t xMax; + /* Xscale numerator */ + uint32_t xScaleNumerator; + /* X range scale value. Set to 0 to enable auto range */ + uint32_t xScaleDenominator; + /* Vertical scaling */ + enum GraphScaleMode scaleMode; + /* RGB background color */ + uint8_t backgroundColor[3]; + /* Horizontal scrolling */ + enum GraphScrollMode scrollMode; +}; + +struct MsgConfigAxis { + /* ID of new axis */ + uint16_t axisId; + /* ID of graph */ + uint16_t graphId; + /* Range Ymin value */ + int32_t yMin; + /* Range Ymax value */ + int32_t yMax; + /* X range scale value. Set to 0 to enable auto range */ + uint32_t xScaleNumerator; + /* X range scale value. Set to 0 to enable auto range */ + uint32_t xScaleDenominator; + /* Mode */ + uint8_t mode; // TODO + /* RGB color */ + uint8_t color[3]; +}; + +struct MsgAddStreamToAxis { + /* ID of graph */ + uint16_t graphId; + /* ID of new axis */ + uint16_t axisId; + /* ID of stream */ + uint16_t streamId; + /* Sample rate of stream, set to 0 if NA */ + uint32_t sampleRateNumerator; + /* Sample rate of stream, set to 0 if NA */ + uint32_t sampleRateDenominator; + /* Range Ymin value */ + uint32_t yScaleNumerator; + /* Range Ymax value */ + uint32_t yScaleDenominator; + /* Offset of values */ + uint32_t yOffset; + /* Adjust the transparency */ + uint8_t transparency; + /* For graphs: bit 0 = line on/off + * bit 1 = points on/off + * For text: bit 0 = flag + * bit 1 = text + */ + uint8_t mode; // TODO + /* Thickness of line */ + uint8_t lineThickness; + /* RGB color of line */ + uint8_t lineColor[3]; +}; + +struct MsgAddCursorToGraph { + /* ID of streama */ + uint16_t streamId; + /* ID of graph */ + uint16_t graphId; + /* ID of axis */ + uint16_t axisId; + /* Thickness of line */ + uint8_t thickness; + /* RGB color of cursor */ + uint8_t color[3]; + /* Starting point of cursor */ + uint32_t initialValue; + /* Minimum allowed value */ + uint32_t minimumValue; + /* Maximum */ + uint32_t maximumValue; + /* Numerator of scaling value */ + uint32_t scaleNumerator; + /* Denominator of scaling value */ + uint32_t scaleDenominator; + /* Offset of value */ + uint32_t scaleOffset; + /* The style of line: Solid, dashed, dotted.. */ + uint8_t lineStyle; // TODO +}; + +struct MsgConfigGpioToGraph { + /* ID of graph */ + uint16_t graphId; + /* GPIO number to add to graph. Bit 0: GPIO0. bit 1: GPIO1 etc. */ + uint8_t gpioNumber; + /* Used to group graphs and cursors to the same scale */ + uint8_t groupId; + /* Adjust the transparency */ + uint8_t transparency; + /* Mode */ + uint16_t mode; // TODO + /* Thickness of line */ + uint8_t lineThickness; + /* RGB color of line when GPIO pin is high */ + uint8_t lineColorHighState[3]; + /* RGB color of line when GPIO pin is low */ + uint8_t lineColorLowState[3]; + /* The style of line */ + uint8_t lineStyle; +}; + +struct MsgConfigTerminal { + /* ID of terminal */ + uint16_t terminalId; + /* Number of characters wide */ + uint8_t width; + /* Number of characters high */ + uint8_t height; + /* RGB background color */ + uint8_t backgroundColor[3]; + /* RGB background color */ + uint8_t foregroundColor[3]; +}; + +struct MsgConfigAddStreamToTerminal { + /* ID of Terminal */ + uint16_t terminalId; + /* ID of stream */ + uint16_t streamId; + /* 0bx x x N T S F F + * N = implicit newline in incoming text + * T = enable tag + * S = timestamped + * F = format (Hex, decimal, binary, ascii) + */ + uint8_t mode; // TODO + /* RGB color of the text stream received */ + uint8_t textColor[3]; + /* RGB color of the tag text */ + uint8_t tagTextColor[3]; +}; + +struct MsgConfigDahsboard { + uint16_t dashboardId; + uint8_t color[3]; + uint16_t height; +}; + +struct MsgConfigDashboardElementCommon { + /* Dashboard ID */ + uint16_t dashboardId; + /* Unique ID of element */ + uint16_t elementId; + /* Order index */ + uint8_t zIndex; + /* X-coordinate of element location. 0 is leftmost position on dashboard */ + uint16_t x; + /* Y-coordinate of element location. 0 is topmost position on dashboard */ + uint16_t y; + /* Width of element */ + uint16_t width; + /* Height of element */ + uint16_t height; + /* See each element type below */ + DashboardElementType elementType; +}; + +struct MsgConfigDashboardElementLabel { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint8_t fontSize; + uint8_t attribute; + LabelAligmentHorisontal horisontalAlignment; + LabelAligmentVertical verticalAlignment; + uint8_t backgroundTransparency; + uint8_t backgroundColor[3]; + uint8_t foregroundTransparency; + uint8_t foregroundColor[3]; +}; + +struct MsgConfigDashboardElementButton { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint8_t fontSize; + uint8_t toggle; +}; + +struct MsgConfigDashboardElementSlider { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint32_t minimumValue; + uint32_t maximumValue; + uint32_t initialValue; +}; + +struct MsgConfigDashboardElementSignal { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint8_t onTransparency; + uint8_t onColor[3]; + uint8_t offTransparency; + uint8_t offColor[3]; +}; + +struct MsgConfigDashboardElementProgress { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elemntType; + uint32_t minimumValue; + uint32_t maximumValue; + uint32_t initialValue; + uint8_t color[3]; +}; + +struct MsgConfigDashboardElementSegment { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + /* Values: 1 ~ 20 */ + uint8_t segmentCount; + /* Values: 2 ~ 16*/ + uint8_t base; + uint8_t transparency; + uint8_t color[3]; +}; + +typedef union { + struct { + uint8_t mouse : 1; + uint8_t fitGraph : 1; + uint8_t autoscale : 1; + uint8_t scrollByTime : 1; + uint8_t : 4; + uint8_t showPlot : 1; + uint8_t showPoints : 1; + uint8_t : 6; + } bit; + uint16_t reg; +} modeType; + +struct MsgConfigDashboardElementGraph { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint8_t titleColor[3]; + uint8_t backgroundColor[3]; + uint8_t graphBackgroundColor[3]; + uint8_t plotCount; + float xMin; + float xMax; + float yMin; + float yMax; + modeType mode; +}; + +struct MsgConfigDashboardElementText { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint8_t minimum[4]; + uint8_t maximum[4]; + uint8_t value[4]; +}; + +struct MsgConfigDashboardElementRadio { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint8_t fontSize; + uint8_t numberItems; + RadioOrientation orientation; +}; + +struct MsgConfigDashboardElementPie { + uint16_t dashboardId; + uint16_t elementId; + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + DashboardElementType elementType; + uint8_t backgroundColor[3]; + uint8_t titleColor[3]; + uint8_t numberSlices; +}; + +struct MsgConfigAddStreamToElement { + uint16_t dashboardId; + uint16_t elementId; + uint16_t streamId; +}; + +struct MsgDataStreamData { + uint16_t streamId; + uint8_t dataSize; + uint8_t* data; +}; + +struct MsgDataStream { + uint8_t numberOfStreams; + MsgDataStreamData stream[ADP_MAX_OUTGOING_STREAMS]; +}; + +struct AtmelDataGateway { + virtual void transmit(uint8_t* txBuffer, uint16_t length); + virtual uint16_t receive(uint8_t* rxBuffer, uint16_t length); + virtual uint16_t transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length); +}; + +class AtmelDataProtocol { + private: + bool packetReceived; + uint8_t prevData; + uint8_t lastReceivedMessageId; + uint8_t rxPacketBuffer[MSG_RES_DATA_PACKET_MAX_LEN]; + uint16_t bytesReceived; + uint16_t lengthReceived; + RxState rxState; + AtmelDataGateway* gateway; + + bool addReceiveByte(uint8_t data); + bool isReceived(void); + bool protocolAddByte(uint8_t rxId, uint8_t *rxBuffer, uint16_t rxLength, uint8_t *rxPacket, uint16_t rxPacketLength); + bool checkForResponse(uint8_t rxId, uint8_t *rxPacket, uint16_t rxPacketLength); + void waitForResponse(uint8_t rxId, uint8_t *rxPacket, uint16_t rxPacketLength); + uint8_t packetReceiveGetId(void); + uint16_t addSendByteDashboard(uint8_t *addBuffer, uint16_t index, struct MsgConfigDashboardElementCommon *const config); + uint16_t verifyDataLength(uint16_t length); + + public: + AtmelDataProtocol(void); + + HandshakeStatus waitForHandshake(void); + StatusCode requestStatus(void); + void addAtmelDataGateway(AtmelDataGateway* adg); + void setColor(uint8_t *structMember, RgbColor color); + bool requestHandshake(uint8_t protocolVersion, uint8_t options, uint8_t *protocolBuffer); + bool receivePacketData(uint8_t *receiveBuffer); + bool configureInfo(const char *title, const char *description); + void configureStreamGetDefaults(MsgConfigStream *const config); + bool configureStream(MsgConfigStream *const config, const char *label); + bool toggleStream(MsgToggleStream *const config); + void configureGraphGetDefaults(MsgConfigGraph *const config); + bool configureGraph(MsgConfigGraph *const config, const char *graphLabel, const char *xLabel); + void addAxisToGraphGetDefaults(MsgConfigAxis *const config); + bool addAxisToGraph(MsgConfigAxis *const config, const char *label); + void addStreamToAxisGetDefaults(MsgAddStreamToAxis *const config); + bool addStreamToAxis(MsgAddStreamToAxis *const config); + void addCursorToGraphGetDefaults(MsgAddCursorToGraph *const config); + bool addCursorToGraph(MsgAddCursorToGraph *const config, const char *label); + void addGpioToGraphGetDefaults(MsgConfigGpioToGraph *const config); + bool addGpioToGraph(MsgConfigGpioToGraph *const config, const char *tagHighState, const char *tagLowState); + void configureTerminalGetDefaults(MsgConfigTerminal *const config); + bool configureTerminal(MsgConfigTerminal *const config, const char *label); + void addStreamToTerminalGetDefaults(MsgConfigAddStreamToTerminal *const config); + bool addStreamToTerminal(MsgConfigAddStreamToTerminal *const config, const char *tagText); + void configureDashboardGetDefaults(MsgConfigDahsboard *const config); + bool addDashboard(MsgConfigDahsboard *const config, const char *label); + + void configureDashboardElementGetDefaults(MsgConfigDashboardElementCommon *const config); + + void configureDashboardLabelGetDefaults(MsgConfigDashboardElementLabel *const config); + bool addLabelToDashboard(MsgConfigDashboardElementLabel *const config, const char *label); + + void configureDashboardButtonGetDefaults(MsgConfigDashboardElementButton *const config); + bool addButtonToDashboard(MsgConfigDashboardElementButton *const config, const char *label); + + void configureDashboardSliderGetDefaults(MsgConfigDashboardElementSlider *const config); + bool addSliderToDashboard(MsgConfigDashboardElementSlider *const config); + + void configureDashboardSignalGetDefaults(MsgConfigDashboardElementSignal *const config); + bool addSignalToDashboard(MsgConfigDashboardElementSignal *const config); + + void configureDashboardPrograssGetDefaults(MsgConfigDashboardElementProgress *const config); + bool addProgressToDashboard(MsgConfigDashboardElementProgress *const config); + + void configureDashboardSegmentGetDefaults(MsgConfigDashboardElementSegment *const config); + bool addSegmentToDashboard(MsgConfigDashboardElementSegment *const config); + + void configureDashboardGraphGetDefaults(MsgConfigDashboardElementGraph *const config); + bool addGraphToDashboard(MsgConfigDashboardElementGraph *const config, const char *title); + + void configureDashboardRadioGetDefaults(MsgConfigDashboardElementRadio *const config); + bool addRadioToDashboard(MsgConfigDashboardElementRadio *const config, const char *text); + + void configureDashboardPieGetDefaults(MsgConfigDashboardElementPie *const config); + bool addPieToDashboard(MsgConfigDashboardElementPie *const config, const char *title); + + void configureDashboardTextGetDefaults(MsgConfigDashboardElementText *const config); + bool addTextToDashboard(MsgConfigDashboardElementText *const config); + + bool addStreamToElement(MsgConfigAddStreamToElement *const config); + bool transceiveStream(MsgDataStream *const streamData, uint8_t *receiveBuffer); + bool transceiveSingleStream(uint16_t streamId, uint8_t *data, uint8_t dataSize, uint8_t *receiveBuffer); + uint16_t addSendByte(uint8_t *buffer, uint8_t index, uint8_t *data, uint16_t length); +}; + +#endif /* ATMEL_DATA_GATEWAY_PROTOCOL_H */ diff --git a/src/DataVisualizer.cpp b/src/DataVisualizer.cpp new file mode 100644 index 0000000..f7776f7 --- /dev/null +++ b/src/DataVisualizer.cpp @@ -0,0 +1,366 @@ +#include "DataVisualizer.h" + +/*********************************************************/ +/* Internal */ +/*********************************************************/ + +void DataVisualizer::read(uint8_t* rxBuffer) { + MsgPacketData* adp = (MsgPacketData*)rxBuffer; + + /* discard incorrect atmel data protocol packet */ + if(adp->bytesSent == 0) return; + + for(uint16_t i = 0; i < buffer.length; i++) { + DataPacket* packet = this->buffer.cache[i].packet; + + if(adp->streamId == packet->id) { + + switch(packet->length) { + case LENGTH_N_BYTE: { + packet->sent = adp->bytesSent; + memcpy(packet->data, adp->data, LENGTH_N_BYTE); + break; + } + + case LENGTH_4_BYTE: { + packet->sent = LENGTH_4_BYTE; + uint8_t index = adp->bytesSent - LENGTH_4_BYTE; + memcpy(packet->data, &adp->data[index], LENGTH_4_BYTE); + break; + } + + case LENGTH_1_BYTE: { + packet->sent = LENGTH_1_BYTE; + packet->data[0] = adp->data[0]; + break; + } + } + } + } +} + +void DataVisualizer::write(uint16_t id, uint8_t* data, uint8_t length) { + uint8_t rxData[MSG_RES_DATA_PACKET_MAX_LEN]; + memset(rxData, 0, MSG_RES_DATA_PACKET_MAX_LEN); + + if(this->protocol.transceiveSingleStream(id, data, length, rxData)) { + this->read(rxData); + }; +} + +bool DataVisualizer::init(void) { + if(this->handshake) { + if(!this->initialized) { + this->initialized = true; + return true; + } + } + return false; +} + +void DataVisualizer::defaults(void) { + this->index = 0; + this->handshake = false; + this->initialized = false; + this->gateway = GATEWAY_NONE; +} + +void DataVisualizer::release(void) { + for(uint16_t i = 0; i < this->buffer.length; i++) { + free(this->buffer.cache[i].packet); + } + free(this->buffer.cache); +} + +DataPacket* DataVisualizer::pack(uint16_t id, DataLength length) { + this->buffer.length++; + + uint16_t setLength = this->buffer.length; + DataCache* cache = (DataCache*) malloc(sizeof(DataCache) * setLength); + memset(cache, 0 , sizeof(DataCache) * setLength); + + uint16_t copyLength = this->buffer.length - 1; + memcpy(cache, this->buffer.cache, sizeof(DataCache) * copyLength); + + free(this->buffer.cache); + this->buffer.cache = cache; + + uint16_t packetIndex = this->buffer.length - 1; + this->buffer.cache[packetIndex].packet = new DataPacket; + + DataPacket* packet = this->buffer.cache[packetIndex].packet; + packet->id = id; + packet->sent = 0; + packet->length = length; + packet->data = new uint8_t[length]; + memset(packet->data, 0, length); + + return packet; +} + +/*********************************************************/ +/* Common */ +/*********************************************************/ + +DataVisualizer::DataVisualizer(void) { + this->protocol.addAtmelDataGateway(this); + this->defaults(); +} + +bool DataVisualizer::setup(Configuration config) { + switch(config) { + case CONFIGURATION_NONE: + return this->init(); + + case CONFIGURATION_AUTOSTART: + this->request(); + this->refresh(); + return this->init(); + } + + return 0; +} + +bool DataVisualizer::request(void) { + if(!this->handshake) { + uint8_t handshakeStatus; + if(this->protocol.requestHandshake(ADP_VERSION, 0, &handshakeStatus)) { + if(handshakeStatus == HANDSHAKE_ACCEPTED) { + this->handshake = true; + } + } + } + return this->handshake; +} + +void DataVisualizer::refresh(void) { + if(this->handshake) { + uint8_t rxData[MSG_RES_DATA_PACKET_MAX_LEN]; + memset(rxData, 0, MSG_RES_DATA_PACKET_MAX_LEN); + + if(this->protocol.receivePacketData(rxData)) { + this->read(rxData); + } + } +} + +void DataVisualizer::reset(void) { + this->defaults(); + this->release(); +} + +/*********************************************************/ +/* Elements */ +/*********************************************************/ + +void DataVisualizer::addInfo(const char *title, const char *description) { + if(!this->handshake) return; + + this->protocol.configureInfo(title, description); +} + +DataVisualizerTerminal DataVisualizer::addTerminal(const char *title) { + return this->addTerminal(title, COLOR_WHITE, COLOR_BLACK); +} + +DataVisualizerTerminal DataVisualizer::addTerminal(const char *title, RgbColor bgColor, RgbColor fgColor) { + DataVisualizerTerminal terminal; + + if(!this->handshake) return terminal; + + uint16_t terminalId = this->index++; + uint16_t terminalStreamIdIn = this->index++; + uint16_t terminalStreamIdOut = this->index++; + + terminal.visualizer = this; + terminal.id = terminalStreamIdOut; + terminal.packet = this->pack(terminalStreamIdIn, LENGTH_N_BYTE); + + MsgConfigTerminal msgConfigTerminal; + this->protocol.configureTerminalGetDefaults(&msgConfigTerminal); + msgConfigTerminal.terminalId = terminalId; + this->protocol.setColor(msgConfigTerminal.backgroundColor, bgColor); + this->protocol.setColor(msgConfigTerminal.foregroundColor, fgColor); + this->protocol.configureTerminal(&msgConfigTerminal, title); + + MsgConfigStream msgConfigStream; + this->protocol.configureStreamGetDefaults(&msgConfigStream); + msgConfigStream.streamId = terminalStreamIdIn; + msgConfigStream.type = STREAM_STRING; + msgConfigStream.mode = STREAM_IN; + msgConfigStream.state = STREAM_ON; + this->protocol.configureStream(&msgConfigStream, "TerminalStreamIn"); + + MsgConfigAddStreamToTerminal msgConfigTerminalStream; + this->protocol.addStreamToTerminalGetDefaults(&msgConfigTerminalStream); + msgConfigTerminalStream.terminalId = terminalId; + msgConfigTerminalStream.streamId = terminalStreamIdIn; + this->protocol.addStreamToTerminal(&msgConfigTerminalStream, "AddTerminalStreamIn"); + + this->protocol.configureStreamGetDefaults(&msgConfigStream); + msgConfigStream.streamId = terminalStreamIdOut; + msgConfigStream.type = STREAM_STRING; + msgConfigStream.mode = STREAM_OUT; + msgConfigStream.state = STREAM_ON; + this->protocol.configureStream(&msgConfigStream, "TerminalStreamOut"); + + this->protocol.addStreamToTerminalGetDefaults(&msgConfigTerminalStream); + msgConfigTerminalStream.terminalId = terminalId; + msgConfigTerminalStream.streamId = terminalStreamIdOut; + this->protocol.addStreamToTerminal(&msgConfigTerminalStream, "AddTerminalStreamOut"); + + return terminal; +} + +DataVisualizerGraph DataVisualizer::addGraph(const char* title) { + return this->addGraph(title, COLOR_BLACK); +} + +DataVisualizerGraph DataVisualizer::addGraph(const char* title, RgbColor bgColor) { + DataVisualizerGraph graph; + + if(!this->handshake) return graph; + + uint16_t graphId = this->index++; + graph.visualizer = this; + graph.id = graphId; + + MsgConfigGraph msgConfigGraph; + this->protocol.configureGraphGetDefaults(&msgConfigGraph); + msgConfigGraph.graphId = graphId; + this->protocol.setColor(msgConfigGraph.backgroundColor, bgColor); + this->protocol.configureGraph(&msgConfigGraph, title, "graph"); + + return graph; +} + +DataVisualizerDashboard DataVisualizer::addDashboard(const char* title) { + return this->addDashboard(title, COLOR_WHITE, 500); +} + +DataVisualizerDashboard DataVisualizer::addDashboard(const char* title, RgbColor color, uint16_t height) { + DataVisualizerDashboard dashboard; + + if(!this->handshake) return dashboard; + + uint16_t dashboardId = this->index++; + dashboard.visualizer = this; + dashboard.id = dashboardId; + + MsgConfigDahsboard msgConfigDashboard; + this->protocol.configureDashboardGetDefaults(&msgConfigDashboard); + msgConfigDashboard.dashboardId = dashboardId; + msgConfigDashboard.height = height; + this->protocol.setColor(msgConfigDashboard.color, color); + this->protocol.addDashboard(&msgConfigDashboard, title); + + return dashboard; +} + +/*********************************************************/ +/* Gateway */ +/*********************************************************/ + +void DataVisualizer::onTransmit(void (*f)(uint8_t*, uint16_t)) { + this->transmitCallback = f; +} + +void DataVisualizer::onReceive(uint16_t (*f)(uint8_t*, uint16_t)) { + this->receiveCallback = f; +} + +void DataVisualizer::onTransceive(uint16_t (*f)(uint8_t*, uint8_t*, uint16_t)) { + this->transceiveCallback = f; +} + +void DataVisualizer::transmit(uint8_t* txBuffer, uint16_t length) { + if(this->gateway == GATEWAY_EXTERN) + this->transmitCallback(txBuffer, length); +#ifdef GATEWAY_INCLUDED_UART + if(this->gateway == GATEWAY_UART) + this->gatewayUart.transmit(txBuffer, length); +#endif +#ifdef GATEWAY_INCLUDED_TWI + if(this->gateway == GATEWAY_TWI) + this->gatewayTwi.transmit(txBuffer, length); +#endif +#ifdef GATEWAY_INCLUDED_SPI + if(this->gateway == GATEWAY_SPI) + this->gatewaySpi.transmit(txBuffer, length); +#endif +} + +uint16_t DataVisualizer::receive(uint8_t* rxBuffer, uint16_t length) { + if(this->gateway == GATEWAY_EXTERN) + return this->receiveCallback(rxBuffer, length); +#ifdef GATEWAY_INCLUDED_UART + if(this->gateway == GATEWAY_UART) + return this->gatewayUart.receive(rxBuffer, length); +#endif +#ifdef GATEWAY_INCLUDED_TWI + if(this->gateway == GATEWAY_TWI) + return this->gatewayTwi.receive(rxBuffer, length); +#endif +#ifdef GATEWAY_INCLUDED_SPI + if(this->gateway == GATEWAY_SPI) + return this->gatewaySpi.receive(rxBuffer, length); +#endif + return 0; +} + +uint16_t DataVisualizer::transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length) { + if(this->gateway == GATEWAY_EXTERN) + return this->transceiveCallback(txBuffer, rxBuffer, length); +#ifdef GATEWAY_INCLUDED_UART + if(this->gateway == GATEWAY_UART) + return this->gatewayUart.transceive(txBuffer, rxBuffer, length); +#endif +#ifdef GATEWAY_INCLUDED_TWI + if(this->gateway == GATEWAY_TWI) + return this->gatewayTwi.transceive(txBuffer, rxBuffer, length); +#endif +#ifdef GATEWAY_INCLUDED_SPI + if(this->gateway == GATEWAY_SPI) + return this->gatewaySpi.transceive(txBuffer, rxBuffer, length); +#endif + return 0; +} + +void DataVisualizer::begin(DataGateway com) { + this->gateway = com; +#ifdef GATEWAY_INCLUDED_UART + if(com == GATEWAY_UART) + this->gatewayUart.begin(); +#endif +#ifdef GATEWAY_INCLUDED_TWI + if(com == GATEWAY_TWI) + this->gatewayTwi.begin(); +#endif +#ifdef GATEWAY_INCLUDED_SPI + if(com == GATEWAY_SPI) + this->gatewaySpi.begin(); +#endif +} + +#ifdef GATEWAY_INCLUDED_UART +void DataVisualizer::begin(Stream* uart) { + this->gateway = GATEWAY_UART; + this->gatewayUart.begin(uart); +} +#endif + +#ifdef GATEWAY_INCLUDED_TWI +void DataVisualizer::begin(TwoWire* twi, uint8_t address) { + this->gateway = GATEWAY_TWI; + this->gatewayTwi.begin(twi, address); +} +#endif + +#ifdef GATEWAY_INCLUDED_SPI +void DataVisualizer::begin(SPIClass* spi, SPISettings settings, uint8_t ss) { + this->gateway = GATEWAY_SPI; + this->gatewaySpi.begin(spi, settings, ss); +} +#endif + +DataVisualizer Visualizer = DataVisualizer(); \ No newline at end of file diff --git a/src/DataVisualizer.h b/src/DataVisualizer.h new file mode 100644 index 0000000..79e8c68 --- /dev/null +++ b/src/DataVisualizer.h @@ -0,0 +1,181 @@ +#ifndef DATA_VISUALIZER_H +#define DATA_VISUALIZER_H + +#include +#include +#include +#include + +#include "AtmelDataProtocol.h" +#include "AtmelDataGatewayUart.h" +#include "AtmelDataGatewaySpi.h" +#include "AtmelDataGatewayTwi.h" +#include "DataVisualizerTerminal.h" +#include "DataVisualizerGraph.h" +#include "DataVisualizerGraphAxis.h" +#include "DataVisualizerGraphAxisCursor.h" +#include "DataVisualizerGraphAxisChannel.h" +#include "DataVisualizerDashboard.h" +#include "DataVisualizerDashboardButton.h" +#include "DataVisualizerDashboardNumericInput.h" +#include "DataVisualizerDashboardLabel.h" +#include "DataVisualizerDashboardSignal.h" +#include "DataVisualizerDashboardRadioGroup.h" +#include "DataVisualizerDashboardGraph.h" +#include "DataVisualizerDashboardGraphChannel.h" + +enum Configuration { + CONFIGURATION_NONE, + CONFIGURATION_AUTOSTART +}; + +enum DataGateway { + GATEWAY_NONE, + GATEWAY_EXTERN, + GATEWAY_TWI, + GATEWAY_SPI, + GATEWAY_UART, + GATEWAY_SERIAL = GATEWAY_UART +}; + +enum DataLength { + LENGTH_1_BYTE = 1, + LENGTH_4_BYTE = 4, + LENGTH_N_BYTE = MSG_RES_DATA_MAX_LEN +}; + +struct DataPacket { + uint16_t id; + uint16_t sent; + uint8_t* data; + DataLength length; +}; + +struct DataCache { + DataPacket* packet; +}; + +struct DataBuffer { + uint16_t length; + DataCache* cache; +}; + +class DataVisualizerGraph; +class DataVisualizerTerminal; +class DataVisualizerDashboard; +class DataVisualizer : AtmelDataGateway { + friend class DataVisualizerTerminal; + friend class DataVisualizerGraph; + friend class DataVisualizerGraphAxis; + friend class DataVisualizerGraphAxisChannel; + friend class DataVisualizerGraphAxisCursor; + friend class DataVisualizerDashboard; + friend class DataVisualizerDashboardButton; + friend class DataVisualizerDashboardNumericInput; + friend class DataVisualizerDashboardSignal; + friend class DataVisualizerDashboardRadioGroup; + friend class DataVisualizerDashboardGraph; + friend class DataVisualizerDashboardGraphChannel; + + private: + bool handshake; + bool initialized; + uint16_t index; + DataBuffer buffer; + AtmelDataProtocol protocol; + + /*********************************************************/ + /* Internal */ + /*********************************************************/ + bool init(void); + void defaults(void); + void release(void); + void read(uint8_t* rxBuffer); + void write(uint16_t id, uint8_t* data, uint8_t length); + DataPacket* pack(uint16_t id, DataLength length); + + public: + DataVisualizer(void); + + /*********************************************************/ + /* Common */ + /*********************************************************/ + bool setup(Configuration config); + bool request(void); + void refresh(void); + void reset(void); + + /*********************************************************/ + /* Elements */ + /*********************************************************/ + void addInfo(const char* title, const char* description); + DataVisualizerTerminal addTerminal(const char* title); + DataVisualizerTerminal addTerminal(const char* title, RgbColor bgColor, RgbColor fgColor); + DataVisualizerGraph addGraph(const char* title); + DataVisualizerGraph addGraph(const char* title, RgbColor bgColor); + DataVisualizerDashboard addDashboard(const char* title); + DataVisualizerDashboard addDashboard(const char* title, RgbColor color, uint16_t height); + + /*********************************************************/ + /* Gateway */ + /*********************************************************/ + private: + DataGateway gateway; + + virtual void transmit(uint8_t* txBuffer, uint16_t length); + virtual uint16_t receive(uint8_t* rxBuffer, uint16_t length); + virtual uint16_t transceive(uint8_t* txBuffer, uint8_t* rxBuffer, uint16_t length); + + public: + void begin(DataGateway com); + + /*********************************************************/ + /* Gateway External */ + /*********************************************************/ + private: + void (*transmitCallback)(uint8_t*, uint16_t) = NULL; + uint16_t (*receiveCallback)(uint8_t*, uint16_t) = NULL; + uint16_t (*transceiveCallback)(uint8_t*, uint8_t*, uint16_t) = NULL; + + public: + void onTransmit(void (*)(uint8_t*, uint16_t)); + void onReceive(uint16_t (*)(uint8_t*, uint16_t)); + void onTransceive(uint16_t (*)(uint8_t*, uint8_t*, uint16_t)); + +#ifdef GATEWAY_INCLUDED_UART + /*********************************************************/ + /* Gateway Universal Asynchronous Receiver Transmitter */ + /*********************************************************/ + private: + AtmelDataGatewayUart gatewayUart; + + public: + void begin(Stream* uart); +#endif + +#ifdef GATEWAY_INCLUDED_TWI + /*********************************************************/ + /* Gateway Two Wire Interface */ + /*********************************************************/ + private: + AtmelDataGatewayTwi gatewayTwi; + + public: + void begin(TwoWire* twi, uint8_t address); +#endif + +#ifdef GATEWAY_INCLUDED_SPI + /*********************************************************/ + /* Gateway Serial Peripheral Interface */ + /*********************************************************/ + private: + AtmelDataGatewaySpi gatewaySpi; + + public: + void begin(SPIClass* spi, SPISettings settings, uint8_t ss); +#endif +}; + +extern DataVisualizer Visualizer; + +#endif /* DATA_VISUALIZER_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboard.cpp b/src/DataVisualizerDashboard.cpp new file mode 100644 index 0000000..96086d0 --- /dev/null +++ b/src/DataVisualizerDashboard.cpp @@ -0,0 +1,427 @@ +#include "DataVisualizerDashboard.h" + +DataVisualizerDashboard::DataVisualizerDashboard(void) { + this->id = 0; + this->visualizer = 0; +} + +DataVisualizerDashboardLabel DataVisualizerDashboard::addLabel(const uint8_t* config) { + DataVisualizerDashboardLabel dashboardLabel; + + if(config[POSITION_TYPE] != DB_TYPE_LABEL) return dashboardLabel; + + uint8_t length = strlen((const char*)(config + POSITION_LABEL_TEXT)) + 1; + char text[length]; + memcpy(&text, config + POSITION_LABEL_TEXT, length); + + ConfigDashboardLabel configDashboardLabel; + memcpy(&configDashboardLabel.zIndex, config + POSITION_Z_INDEX, sizeof(configDashboardLabel.zIndex)); + memcpy(&configDashboardLabel.x, config + POSITION_X, sizeof(configDashboardLabel.x)); + memcpy(&configDashboardLabel.y, config + POSITION_Y, sizeof(configDashboardLabel.y)); + memcpy(&configDashboardLabel.width, config + POSITION_WIDTH, sizeof(configDashboardLabel.width)); + memcpy(&configDashboardLabel.height, config + POSITION_HEIGHT, sizeof(configDashboardLabel.height)); + memcpy(&configDashboardLabel.fontSize, config + POSITION_LABEL_FONT, sizeof(configDashboardLabel.fontSize)); + memcpy(&configDashboardLabel.backgroundAlpha, config + POSITION_LABEL_ALPHA_BACKGROUND, sizeof(configDashboardLabel.backgroundAlpha)); + memcpy(&configDashboardLabel.forgroundAlpha, config + POSITION_LABEL_ALPHA_FOREGROUND, sizeof(configDashboardLabel.forgroundAlpha)); + memcpy(&configDashboardLabel.attribute, config + POSITION_LABEL_ATTRIBUTE, sizeof(configDashboardLabel.attribute)); + memcpy(&configDashboardLabel.aligmentHorisontal, config + POSITION_LABEL_HOR_ALIG, sizeof(configDashboardLabel.aligmentHorisontal)); + memcpy(&configDashboardLabel.aligmentVertical, config + POSITION_LABEL_VER_ALIG, sizeof(configDashboardLabel.aligmentVertical)); + memcpy(&configDashboardLabel.backgroundColor, config + POSITION_LABEL_COLOR_BACKGROUND, sizeof(configDashboardLabel.backgroundColor)); + memcpy(&configDashboardLabel.forgroundColor, config + POSITION_LABEL_COLOR_FOREGROUND, sizeof(configDashboardLabel.forgroundColor)); + + this->addLabel(text, configDashboardLabel); +} + +DataVisualizerDashboardLabel DataVisualizerDashboard::addLabel(const char* text, ConfigDashboardLabel config) { + DataVisualizerDashboardLabel dashboardLabel; + + if(!this->visualizer) return dashboardLabel; + if(!this->visualizer->handshake) return dashboardLabel; + + uint16_t elementId = this->visualizer->index++; + + dashboardLabel.visualizer = this->visualizer; + dashboardLabel.id = elementId; + + MsgConfigDashboardElementLabel msgConfigDashboardElementLabel; + this->visualizer->protocol.configureDashboardLabelGetDefaults(&msgConfigDashboardElementLabel); + msgConfigDashboardElementLabel.elementType = ELEMENT_TYPE_LABEL; + msgConfigDashboardElementLabel.dashboardId = this->id; + msgConfigDashboardElementLabel.elementId = elementId; + msgConfigDashboardElementLabel.zIndex = config.zIndex; + msgConfigDashboardElementLabel.x = config.x; + msgConfigDashboardElementLabel.y = config.y; + msgConfigDashboardElementLabel.width = config.width; + msgConfigDashboardElementLabel.height = config.height; + msgConfigDashboardElementLabel.fontSize = config.fontSize; + msgConfigDashboardElementLabel.attribute = config.attribute; + msgConfigDashboardElementLabel.horisontalAlignment = config.aligmentHorisontal; + msgConfigDashboardElementLabel.verticalAlignment = config.aligmentVertical; + msgConfigDashboardElementLabel.backgroundTransparency = config.backgroundAlpha; + msgConfigDashboardElementLabel.foregroundTransparency = config.forgroundAlpha; + this->visualizer->protocol.setColor(msgConfigDashboardElementLabel.backgroundColor, config.backgroundColor); + this->visualizer->protocol.setColor(msgConfigDashboardElementLabel.foregroundColor, config.forgroundColor); + this->visualizer->protocol.addLabelToDashboard(&msgConfigDashboardElementLabel, text); + + return dashboardLabel; +} + +DataVisualizerDashboardNumericInput DataVisualizerDashboard::addNumericInput(const uint8_t* config) { + DataVisualizerDashboardNumericInput dashboardNumericInput; + + if(config[POSITION_TYPE] != DB_TYPE_TEXT) return dashboardNumericInput; + + ConfigDashboardNumericInput configDashboardNumericInput; + memcpy(&configDashboardNumericInput.zIndex, config + POSITION_Z_INDEX, sizeof(configDashboardNumericInput.zIndex)); + memcpy(&configDashboardNumericInput.x, config + POSITION_X, sizeof(configDashboardNumericInput.x)); + memcpy(&configDashboardNumericInput.y, config + POSITION_Y, sizeof(configDashboardNumericInput.y)); + memcpy(&configDashboardNumericInput.width, config + POSITION_WIDTH, sizeof(configDashboardNumericInput.width)); + memcpy(&configDashboardNumericInput.height, config + POSITION_HEIGHT, sizeof(configDashboardNumericInput.height)); + memcpy(&configDashboardNumericInput.minimum, config + POSITION_TEXT_MINIMUM, sizeof(configDashboardNumericInput.minimum)); + memcpy(&configDashboardNumericInput.maximum, config + POSITION_TEXT_MAXIMUM, sizeof(configDashboardNumericInput.maximum)); + memcpy(&configDashboardNumericInput.value, config + POSITION_TEXT_VALUE, sizeof(configDashboardNumericInput.value)); + + return this->addNumericInput(configDashboardNumericInput); +} + +DataVisualizerDashboardNumericInput DataVisualizerDashboard::addNumericInput(ConfigDashboardNumericInput config) { + DataVisualizerDashboardNumericInput dashboardNumericInput; + + if(!this->visualizer) return dashboardNumericInput; + if(!this->visualizer->handshake) return dashboardNumericInput; + + uint16_t elementId = this->visualizer->index++; + uint16_t streamId = this->visualizer->index++; + + dashboardNumericInput.visualizer = this->visualizer; + dashboardNumericInput.id = elementId; + dashboardNumericInput.packet = this->visualizer->pack(streamId, LENGTH_4_BYTE); + memcpy(dashboardNumericInput.packet->data, &config.value, LENGTH_4_BYTE); + + MsgConfigDashboardElementText msgConfigDashboardElementText; + this->visualizer->protocol.configureDashboardTextGetDefaults(&msgConfigDashboardElementText); + msgConfigDashboardElementText.elementType = ELEMENT_TYPE_TEXT; + msgConfigDashboardElementText.dashboardId = this->id; + msgConfigDashboardElementText.elementId = elementId; + msgConfigDashboardElementText.zIndex = config.zIndex; + msgConfigDashboardElementText.x = config.x; + msgConfigDashboardElementText.y = config.y; + msgConfigDashboardElementText.width = config.width; + msgConfigDashboardElementText.height = config.height; + memcpy(msgConfigDashboardElementText.minimum, &config.minimum, LENGTH_4_BYTE); + memcpy(msgConfigDashboardElementText.maximum, &config.maximum, LENGTH_4_BYTE); + memcpy(msgConfigDashboardElementText.value, &config.value, LENGTH_4_BYTE); + this->visualizer->protocol.addTextToDashboard(&msgConfigDashboardElementText); + + MsgConfigStream msgConfigStream; + msgConfigStream.streamId = streamId; + msgConfigStream.type = STREAM_INT_32; + msgConfigStream.mode = STREAM_IN; + msgConfigStream.state = STREAM_ON; + this->visualizer->protocol.configureStream(&msgConfigStream, "NumericInput"); + + MsgConfigAddStreamToElement msgConfigAddStreamToElement; + msgConfigAddStreamToElement.dashboardId = this->id; + msgConfigAddStreamToElement.elementId = elementId; + msgConfigAddStreamToElement.streamId = streamId; + this->visualizer->protocol.addStreamToElement(&msgConfigAddStreamToElement); + + return dashboardNumericInput; +} + +DataVisualizerDashboardButton DataVisualizerDashboard::addButton(const char* text, ConfigDashboardButton config) { + return this->addButton(text, config, VARIANT_TOGGLED_OFF); +} + +DataVisualizerDashboardButton DataVisualizerDashboard::addButton(const char* textOn, const char* textOff, ConfigDashboardButton config) { + + uint8_t length = strlen(textOn) + strlen(textOff) + 2; + + const char delimiter[] = "/"; + char text[length]; + + strcat(text, textOn); + strcat(text, delimiter); + strcat(text, textOff); + + return this->addButton(text, config, VARIANT_TOGGLED_ON); +} + +DataVisualizerDashboardButton DataVisualizerDashboard::addButton(const uint8_t* config) { + DataVisualizerDashboardButton dashboardButton; + + if(config[POSITION_TYPE] != DB_TYPE_BUTTON) return dashboardButton; + + uint8_t length = strlen((const char*)(config + POSITION_BUTTON_TEXT)) + 1; + char text[length]; + memcpy(&text, config + POSITION_BUTTON_TEXT, length); + + ConfigDashboardButton configDashboardButton; + memcpy(&configDashboardButton.zIndex, config + POSITION_Z_INDEX, sizeof(configDashboardButton.zIndex)); + memcpy(&configDashboardButton.x, config + POSITION_X, sizeof(configDashboardButton.x)); + memcpy(&configDashboardButton.y, config + POSITION_Y, sizeof(configDashboardButton.y)); + memcpy(&configDashboardButton.width, config + POSITION_WIDTH, sizeof(configDashboardButton.width)); + memcpy(&configDashboardButton.height, config + POSITION_HEIGHT, sizeof(configDashboardButton.height)); + memcpy(&configDashboardButton.fontSize, config + POSITION_BUTTON_FONT_SIZE, sizeof(configDashboardButton.fontSize)); + + uint8_t toggle = config[POSITION_BUTTON_TEXT + length]; + + return this->addButton(text, configDashboardButton, toggle); +} + +DataVisualizerDashboardButton DataVisualizerDashboard::addButton(const char* text, ConfigDashboardButton config, uint8_t toggle) { + DataVisualizerDashboardButton dashboardButton; + + if(!this->visualizer) return dashboardButton; + if(!this->visualizer->handshake) return dashboardButton; + + uint16_t elementId = this->visualizer->index++; + uint16_t streamId = this->visualizer->index++; + + dashboardButton.visualizer = this->visualizer; + dashboardButton.id = elementId; + dashboardButton.packet = this->visualizer->pack(streamId, LENGTH_1_BYTE); + + MsgConfigDashboardElementButton msgConfigDashboardElementButton; + this->visualizer->protocol.configureDashboardButtonGetDefaults(&msgConfigDashboardElementButton); + msgConfigDashboardElementButton.elementType = ELEMENT_TYPE_BUTTON; + msgConfigDashboardElementButton.dashboardId = this->id; + msgConfigDashboardElementButton.elementId = elementId; + msgConfigDashboardElementButton.zIndex = config.zIndex; + msgConfigDashboardElementButton.x = config.x; + msgConfigDashboardElementButton.y = config.y; + msgConfigDashboardElementButton.width = config.width; + msgConfigDashboardElementButton.height = config.height; + msgConfigDashboardElementButton.fontSize = config.fontSize; + msgConfigDashboardElementButton.toggle = toggle; + this->visualizer->protocol.addButtonToDashboard(&msgConfigDashboardElementButton, text); + + MsgConfigStream msgConfigStream; + msgConfigStream.streamId = streamId; + msgConfigStream.type = STREAM_UINT_8; + msgConfigStream.mode = STREAM_IN; + msgConfigStream.state = STREAM_ON; + this->visualizer->protocol.configureStream(&msgConfigStream, "Button"); + + MsgConfigAddStreamToElement msgConfigAddStreamToElement; + msgConfigAddStreamToElement.dashboardId = this->id; + msgConfigAddStreamToElement.elementId = elementId; + msgConfigAddStreamToElement.streamId = streamId; + this->visualizer->protocol.addStreamToElement(&msgConfigAddStreamToElement); + + return dashboardButton; +} + +DataVisualizerDashboardSignal DataVisualizerDashboard::addSignal(const uint8_t* config) { + DataVisualizerDashboardSignal dashboardSignal; + + if(config[POSITION_TYPE] != DB_TYPE_SIGNAL) return dashboardSignal; + + ConfigDashboardSignal configDashboardSignal; + memcpy(&configDashboardSignal.zIndex, config + POSITION_Z_INDEX, sizeof(configDashboardSignal.zIndex)); + memcpy(&configDashboardSignal.x, config + POSITION_X, sizeof(configDashboardSignal.x)); + memcpy(&configDashboardSignal.y, config + POSITION_Y, sizeof(configDashboardSignal.y)); + memcpy(&configDashboardSignal.width, config + POSITION_WIDTH, sizeof(configDashboardSignal.width)); + memcpy(&configDashboardSignal.height, config + POSITION_HEIGHT, sizeof(configDashboardSignal.height)); + memcpy(&configDashboardSignal.onAlpha, config + POSITION_SIGNAL_ALPHA_ON, sizeof(configDashboardSignal.onAlpha)); + memcpy(&configDashboardSignal.offAlpha, config + POSITION_SIGNAL_ALPHA_OFF, sizeof(configDashboardSignal.offAlpha)); + memcpy(&configDashboardSignal.onColor, config + POSITION_SIGNAL_COLOR_ON, sizeof(configDashboardSignal.onColor)); + memcpy(&configDashboardSignal.offColor, config + POSITION_SIGNAL_COLOR_OFF, sizeof(configDashboardSignal.offColor)); + + return this->addSignal(configDashboardSignal); +} + +DataVisualizerDashboardSignal DataVisualizerDashboard::addSignal(ConfigDashboardSignal config) { + DataVisualizerDashboardSignal dashboardSignal; + + if(!this->visualizer) return dashboardSignal; + if(!this->visualizer->handshake) return dashboardSignal; + + uint16_t elementId = this->visualizer->index++; + uint16_t streamId = this->visualizer->index++; + + dashboardSignal.visualizer = this->visualizer; + dashboardSignal.id = streamId; + + MsgConfigDashboardElementSignal msgConfigCashboardElementSignal; + this->visualizer->protocol.configureDashboardSignalGetDefaults(&msgConfigCashboardElementSignal); + msgConfigCashboardElementSignal.elementType = ELEMENT_TYPE_SIGNAL; + msgConfigCashboardElementSignal.dashboardId = this->id; + msgConfigCashboardElementSignal.elementId = elementId; + msgConfigCashboardElementSignal.zIndex = config.zIndex; + msgConfigCashboardElementSignal.x = config.x; + msgConfigCashboardElementSignal.y = config.y; + msgConfigCashboardElementSignal.width = config.width; + msgConfigCashboardElementSignal.height = config.height; + msgConfigCashboardElementSignal.onTransparency = config.onAlpha; + msgConfigCashboardElementSignal.offTransparency = config.offAlpha; + this->visualizer->protocol.setColor(msgConfigCashboardElementSignal.onColor, config.onColor); + this->visualizer->protocol.setColor(msgConfigCashboardElementSignal.offColor, config.offColor); + this->visualizer->protocol.addSignalToDashboard(&msgConfigCashboardElementSignal); + + MsgConfigStream msgConfigStream; + msgConfigStream.streamId = streamId; + msgConfigStream.type = STREAM_UINT_8; + msgConfigStream.mode = STREAM_OUT; + msgConfigStream.state = STREAM_ON; + this->visualizer->protocol.configureStream(&msgConfigStream, "Signal"); + + MsgConfigAddStreamToElement msgConfigAddStreamToElement; + msgConfigAddStreamToElement.dashboardId = this->id; + msgConfigAddStreamToElement.elementId = elementId; + msgConfigAddStreamToElement.streamId = streamId; + this->visualizer->protocol.addStreamToElement(&msgConfigAddStreamToElement); + + return dashboardSignal; +} + +DataVisualizerDashboardRadioGroup DataVisualizerDashboard::addRadioGroup(const uint8_t* config) { + DataVisualizerDashboardRadioGroup dashboardRadioGroup; + + if(config[POSITION_TYPE] != DB_TYPE_RADIOGROUP) return dashboardRadioGroup; + + uint8_t length = strlen((const char*)(config + POSITION_RADIOGROUP_TEXT)) + 1; + char text[length]; + memcpy(&text, config + POSITION_RADIOGROUP_TEXT, length); + + ConfigDashboardRadioGroup configDashboardRadioGroup; + memcpy(&configDashboardRadioGroup.zIndex, config + POSITION_Z_INDEX, sizeof(configDashboardRadioGroup.zIndex)); + memcpy(&configDashboardRadioGroup.x, config + POSITION_X, sizeof(configDashboardRadioGroup.x)); + memcpy(&configDashboardRadioGroup.y, config + POSITION_Y, sizeof(configDashboardRadioGroup.y)); + memcpy(&configDashboardRadioGroup.width, config + POSITION_WIDTH, sizeof(configDashboardRadioGroup.width)); + memcpy(&configDashboardRadioGroup.height, config + POSITION_HEIGHT, sizeof(configDashboardRadioGroup.height)); + memcpy(&configDashboardRadioGroup.sizeItems, config + POSITION_RADIOGROUP_SIZE_ITEMS, sizeof(configDashboardRadioGroup.sizeItems)); + memcpy(&configDashboardRadioGroup.numberItems, config + POSITION_RADIOGROUP_NUMBER_ITEMS, sizeof(configDashboardRadioGroup.numberItems)); + memcpy(&configDashboardRadioGroup.orientation, config + POSITION_RADIOGROUP_ORIENTATION, sizeof(configDashboardRadioGroup.orientation)); + + return this->addRadioGroup(text, configDashboardRadioGroup); +} + +DataVisualizerDashboardRadioGroup DataVisualizerDashboard::addRadioGroup(ConfigDashboardRadioGroup config) { + config.numberItems = config.numberItems > RADIOGROUP_MAX ? RADIOGROUP_MAX : config.numberItems; + + char text[config.numberItems]; + for(uint8_t i = 0; i < config.numberItems; i++) text[i] = '/'; + + return this->addRadioGroup(text, config); +} + +DataVisualizerDashboardRadioGroup DataVisualizerDashboard::addRadioGroup(const char* text, ConfigDashboardRadioGroup config) { + DataVisualizerDashboardRadioGroup dashboardRadioGroup; + + if(!this->visualizer) return dashboardRadioGroup; + if(!this->visualizer->handshake) return dashboardRadioGroup; + + uint16_t elementId = this->visualizer->index++; + uint16_t streamId = this->visualizer->index++; + + dashboardRadioGroup.visualizer = this->visualizer; + dashboardRadioGroup.id = elementId; + dashboardRadioGroup.packet = this->visualizer->pack(streamId, LENGTH_1_BYTE); + + MsgConfigDashboardElementRadio msgConfigDashboardElementRadio; + this->visualizer->protocol.configureDashboardRadioGetDefaults(&msgConfigDashboardElementRadio); + msgConfigDashboardElementRadio.elementType = ELEMENT_TYPE_RADIO; + msgConfigDashboardElementRadio.dashboardId = this->id; + msgConfigDashboardElementRadio.elementId = elementId; + msgConfigDashboardElementRadio.zIndex = config.zIndex; + msgConfigDashboardElementRadio.x = config.x; + msgConfigDashboardElementRadio.y = config.y; + msgConfigDashboardElementRadio.width = config.width; + msgConfigDashboardElementRadio.height = config.height; + msgConfigDashboardElementRadio.fontSize = config.sizeItems; + msgConfigDashboardElementRadio.orientation = config.orientation; + msgConfigDashboardElementRadio.numberItems = config.numberItems; + this->visualizer->protocol.addRadioToDashboard(&msgConfigDashboardElementRadio, text); + + MsgConfigStream msgConfigStream; + msgConfigStream.streamId = streamId; + msgConfigStream.type = STREAM_UINT_8; + msgConfigStream.mode = STREAM_IN; + msgConfigStream.state = STREAM_ON; + this->visualizer->protocol.configureStream(&msgConfigStream, "RadioGroup"); + + MsgConfigAddStreamToElement msgConfigAddStreamToElement; + msgConfigAddStreamToElement.dashboardId = this->id; + msgConfigAddStreamToElement.elementId = elementId; + msgConfigAddStreamToElement.streamId = streamId; + this->visualizer->protocol.addStreamToElement(&msgConfigAddStreamToElement); + + return dashboardRadioGroup; +} + +DataVisualizerDashboardGraph DataVisualizerDashboard::addGraph(uint8_t* config) { + DataVisualizerDashboardGraph dashboardGraph; + + if(config[POSITION_TYPE] != DB_TYPE_GRAPH) return dashboardGraph; + + uint8_t length = strlen((const char*)(config + POSITION_GRAPH_TEXT)) + 1; + char text[length]; + memcpy(&text, config + POSITION_GRAPH_TEXT, length); + + ConfigDashboardGraph configDashboardGraph; + memcpy(&configDashboardGraph.zIndex, config + POSITION_Z_INDEX, sizeof(configDashboardGraph.zIndex)); + memcpy(&configDashboardGraph.x, config + POSITION_X, sizeof(configDashboardGraph.x)); + memcpy(&configDashboardGraph.y, config + POSITION_Y, sizeof(configDashboardGraph.y)); + memcpy(&configDashboardGraph.width, config + POSITION_WIDTH, sizeof(configDashboardGraph.width)); + memcpy(&configDashboardGraph.height, config + POSITION_HEIGHT, sizeof(configDashboardGraph.height)); + memcpy(&configDashboardGraph.plotCount, config + POSITION_GRAPH_PLOT_COUNT + length, sizeof(configDashboardGraph.plotCount)); + memcpy(&configDashboardGraph.xMinimum, config + POSITION_GRAPH_X_MINIMUM + length, sizeof(configDashboardGraph.xMinimum)); + memcpy(&configDashboardGraph.xMaximum, config + POSITION_GRAPH_X_MAXIMUM + length, sizeof(configDashboardGraph.xMaximum)); + memcpy(&configDashboardGraph.yMinimum, config + POSITION_GRAPH_Y_MINIMUM + length, sizeof(configDashboardGraph.yMinimum)); + memcpy(&configDashboardGraph.yMaximum, config + POSITION_GRAPH_Y_MAXIMUM + length, sizeof(configDashboardGraph.yMaximum)); + memcpy(&configDashboardGraph.titleColor, config + POSITION_GRAPH_COLOR_TITLE, sizeof(configDashboardGraph.titleColor)); + memcpy(&configDashboardGraph.backgroundColor, config + POSITION_GRAPH_COLOR_BACKGROUND, sizeof(configDashboardGraph.backgroundColor)); + memcpy(&configDashboardGraph.graphColor, config + POSITION_GRAPH_COLOR_GRAPH, sizeof(configDashboardGraph.graphColor)); + + configDashboardGraph.mouseInteraction = config[POSITION_GRAPH_MODE_LB + length] & 0x01; + configDashboardGraph.fitToRight = config[POSITION_GRAPH_MODE_LB + length] & 0x02; + configDashboardGraph.autoscale = config[POSITION_GRAPH_MODE_LB + length] & 0x04; + configDashboardGraph.scrollByTime = config[POSITION_GRAPH_MODE_LB + length] & 0x08; + configDashboardGraph.showPlot = config[POSITION_GRAPH_MODE_HB + length] & 0x01; + configDashboardGraph.showPoints = config[POSITION_GRAPH_MODE_HB + length] & 0x02; + + return this->addGraph(text, configDashboardGraph); +} + +DataVisualizerDashboardGraph DataVisualizerDashboard::addGraph(const char* text, ConfigDashboardGraph config) { + DataVisualizerDashboardGraph dashboardGraph; + + if(!this->visualizer) return dashboardGraph; + if(!this->visualizer->handshake) return dashboardGraph; + + uint16_t elementId = this->visualizer->index++; + + dashboardGraph.visualizer = this->visualizer; + dashboardGraph.dashboard = this; + dashboardGraph.id = elementId; + dashboardGraph.plotCount = config.plotCount; + + MsgConfigDashboardElementGraph msgConfigDashboardElementGraph; + this->visualizer->protocol.configureDashboardGraphGetDefaults(&msgConfigDashboardElementGraph); + msgConfigDashboardElementGraph.elementType = ELEMENT_TYPE_GRAPH; + msgConfigDashboardElementGraph.dashboardId = this->id; + msgConfigDashboardElementGraph.elementId = elementId; + msgConfigDashboardElementGraph.zIndex = config.zIndex; + msgConfigDashboardElementGraph.x = config.x; + msgConfigDashboardElementGraph.y = config.y; + msgConfigDashboardElementGraph.width = config.width; + msgConfigDashboardElementGraph.height = config.height; + msgConfigDashboardElementGraph.plotCount = config.plotCount; + msgConfigDashboardElementGraph.xMin = config.xMinimum; + msgConfigDashboardElementGraph.xMax = config.xMaximum; + msgConfigDashboardElementGraph.yMin = config.yMinimum; + msgConfigDashboardElementGraph.yMax = config.yMaximum; + msgConfigDashboardElementGraph.mode.bit.fitGraph = config.fitToRight; + msgConfigDashboardElementGraph.mode.bit.mouse = config.mouseInteraction; + msgConfigDashboardElementGraph.mode.bit.autoscale = config.autoscale; + msgConfigDashboardElementGraph.mode.bit.scrollByTime = config.scrollByTime; + msgConfigDashboardElementGraph.mode.bit.showPlot = config.showPlot; + msgConfigDashboardElementGraph.mode.bit.showPoints = config.showPoints; + this->visualizer->protocol.setColor(msgConfigDashboardElementGraph.titleColor, config.titleColor); + this->visualizer->protocol.setColor(msgConfigDashboardElementGraph.backgroundColor, config.backgroundColor); + this->visualizer->protocol.setColor(msgConfigDashboardElementGraph.graphBackgroundColor, config.graphColor); + this->visualizer->protocol.addGraphToDashboard(&msgConfigDashboardElementGraph, text); + + return dashboardGraph; +} \ No newline at end of file diff --git a/src/DataVisualizerDashboard.h b/src/DataVisualizerDashboard.h new file mode 100644 index 0000000..fef9c3f --- /dev/null +++ b/src/DataVisualizerDashboard.h @@ -0,0 +1,191 @@ +#ifndef DATA_VISUALIZER_DASHBOARD_H +#define DATA_VISUALIZER_DASHBOARD_H + +#include "DataVisualizer.h" + +#define POSITION_TYPE 2 +#define POSITION_Z_INDEX 3 +#define POSITION_X 4 +#define POSITION_Y 6 +#define POSITION_WIDTH 8 +#define POSITION_HEIGHT 10 + +#define POSITION_BUTTON_FONT_SIZE 12 +#define POSITION_BUTTON_TEXT 13 + +#define POSITION_TEXT_MINIMUM 12 +#define POSITION_TEXT_MAXIMUM 16 +#define POSITION_TEXT_VALUE 20 + +#define POSITION_LABEL_FONT 12 +#define POSITION_LABEL_ATTRIBUTE 13 +#define POSITION_LABEL_HOR_ALIG 14 +#define POSITION_LABEL_VER_ALIG 15 +#define POSITION_LABEL_ALPHA_BACKGROUND 16 +#define POSITION_LABEL_COLOR_BACKGROUND 17 +#define POSITION_LABEL_ALPHA_FOREGROUND 20 +#define POSITION_LABEL_COLOR_FOREGROUND 21 +#define POSITION_LABEL_TEXT 24 + +#define POSITION_SIGNAL_ALPHA_ON 12 +#define POSITION_SIGNAL_COLOR_ON 13 +#define POSITION_SIGNAL_ALPHA_OFF 16 +#define POSITION_SIGNAL_COLOR_OFF 17 + +#define POSITION_RADIOGROUP_SIZE_ITEMS 12 +#define POSITION_RADIOGROUP_NUMBER_ITEMS 13 +#define POSITION_RADIOGROUP_ORIENTATION 14 +#define POSITION_RADIOGROUP_TEXT 15 + +#define POSITION_GRAPH_COLOR_TITLE 12 +#define POSITION_GRAPH_COLOR_BACKGROUND 15 +#define POSITION_GRAPH_COLOR_GRAPH 18 +#define POSITION_GRAPH_TEXT 21 +#define POSITION_GRAPH_PLOT_COUNT 21 +#define POSITION_GRAPH_X_MINIMUM 22 +#define POSITION_GRAPH_X_MAXIMUM 26 +#define POSITION_GRAPH_Y_MINIMUM 30 +#define POSITION_GRAPH_Y_MAXIMUM 34 +#define POSITION_GRAPH_MODE_LB 38 +#define POSITION_GRAPH_MODE_HB 39 + +#define RADIOGROUP_MAX 10 + +enum DashboardType { + DB_TYPE_NONE, + DB_TYPE_LABEL, + DB_TYPE_BUTTON, + DB_TYPE_TEXT, + DB_TYPE_SIGNAL, + DB_TYPE_RADIOGROUP, + DB_TYPE_GRAPH +}; + +enum ButtonVariant { + VARIANT_TOGGLED_OFF, + VARIANT_TOGGLED_ON +}; + +struct ConfigDashboardLabel { + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + uint8_t fontSize; + LabelAttribute attribute; + LabelAligmentHorisontal aligmentHorisontal; + LabelAligmentVertical aligmentVertical; + RgbColor backgroundColor; + uint8_t backgroundAlpha; + RgbColor forgroundColor; + uint8_t forgroundAlpha; +}; + +struct ConfigDashboardNumericInput { + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + uint32_t minimum; + uint32_t maximum; + uint32_t value; +}; + +struct ConfigDashboardButton { + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + uint8_t fontSize; +}; + +struct ConfigDashboardSignal { + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + RgbColor onColor; + uint8_t onAlpha; + RgbColor offColor; + uint8_t offAlpha; +}; + +struct ConfigDashboardRadioGroup { + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + uint8_t sizeItems; + uint8_t numberItems; + RadioOrientation orientation; +}; + +struct ConfigDashboardGraph { + uint8_t zIndex; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + RgbColor titleColor; + RgbColor backgroundColor; + RgbColor graphColor; + uint8_t plotCount; + float xMinimum; + float xMaximum; + float yMinimum; + float yMaximum; + bool mouseInteraction; + bool fitToRight; + bool autoscale; + bool scrollByTime; + bool showPlot; + bool showPoints; +}; + +class DataVisualizer; +class DataVisualizerDashboardLabel; +class DataVisualizerDashboardButton; +class DataVisualizerDashboardNumericInput; +class DataVisualizerDashboardSignal; +class DataVisualizerDashboardRadioGroup; +class DataVisualizerDashboardGraph; +class DataVisualizerDashboard { + friend class DataVisualizer; + friend class DataVisualizerDashboardGraph; + + private: + uint16_t id; + DataVisualizer* visualizer; + DataVisualizerDashboardButton addButton(const char* text, ConfigDashboardButton config, uint8_t toggle); + DataVisualizerDashboardRadioGroup addRadioGroup(const char* text, ConfigDashboardRadioGroup config); + + public: + DataVisualizerDashboard(void); + DataVisualizerDashboardLabel addLabel(const uint8_t* config); + DataVisualizerDashboardLabel addLabel(const char* text, ConfigDashboardLabel config); + + DataVisualizerDashboardNumericInput addNumericInput(const uint8_t* config); + DataVisualizerDashboardNumericInput addNumericInput(ConfigDashboardNumericInput config); + + DataVisualizerDashboardButton addButton(const uint8_t* config); + DataVisualizerDashboardButton addButton(const char* text, ConfigDashboardButton config); + DataVisualizerDashboardButton addButton(const char* textOn, const char* textOff, ConfigDashboardButton config); + + DataVisualizerDashboardSignal addSignal(const uint8_t* config); + DataVisualizerDashboardSignal addSignal(ConfigDashboardSignal config); + + DataVisualizerDashboardRadioGroup addRadioGroup(const uint8_t* config); + DataVisualizerDashboardRadioGroup addRadioGroup(ConfigDashboardRadioGroup config); + + DataVisualizerDashboardGraph addGraph(uint8_t* config); + DataVisualizerDashboardGraph addGraph(const char* text, ConfigDashboardGraph config); +}; + +typedef DataVisualizerDashboard Dashboard; + +#endif /* DATA_VISUALIZER_DASHBOARD_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboardButton.cpp b/src/DataVisualizerDashboardButton.cpp new file mode 100644 index 0000000..33d201e --- /dev/null +++ b/src/DataVisualizerDashboardButton.cpp @@ -0,0 +1,31 @@ +#include "DataVisualizerDashboardButton.h" + +DataVisualizerDashboardButton::DataVisualizerDashboardButton(void) { + this->id = 0; + this->toggle = 0; + this->visualizer = 0; + this->packet = 0; +} + +bool DataVisualizerDashboardButton::pressed(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + if(this->packet->sent) { + if(this->packet->data[0]) { + this->toggle = true; + } else { + this->toggle = false; + } + this->packet->data[0] = 0; + this->packet->sent = 0; + return true; + } + + return false; +} + +bool DataVisualizerDashboardButton::toggled(void) { + this->pressed(); + return this->toggle; +} \ No newline at end of file diff --git a/src/DataVisualizerDashboardButton.h b/src/DataVisualizerDashboardButton.h new file mode 100644 index 0000000..5f67f1f --- /dev/null +++ b/src/DataVisualizerDashboardButton.h @@ -0,0 +1,25 @@ +#ifndef DATA_VISUALIZER_DASHBOARD_BUTTON_H +#define DATA_VISUALIZER_DASHBOARD_BUTTON_H + +#include "DataVisualizer.h" + +struct DataPacket; +class DataVisualizer; +class DataVisualizerDashboardButton { + friend class DataVisualizerDashboard; + + private: + bool toggle; + uint16_t id; + DataPacket* packet; + DataVisualizer* visualizer; + + public: + DataVisualizerDashboardButton(void); + bool pressed(void); + bool toggled(void); +}; + +typedef DataVisualizerDashboardButton DashboardButton; + +#endif /* DATA_VISUALIZER_DASHBOARD_BUTTON_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboardGraph.cpp b/src/DataVisualizerDashboardGraph.cpp new file mode 100644 index 0000000..12a123e --- /dev/null +++ b/src/DataVisualizerDashboardGraph.cpp @@ -0,0 +1,36 @@ +#include "DataVisualizerDashboardGraph.h" + +DataVisualizerDashboardGraph::DataVisualizerDashboardGraph(void) { + this->id = 0; + this->visualizer = 0; +} + +DataVisualizerDashboardGraphChannel DataVisualizerDashboardGraph::addChannel(const char* text) { + DataVisualizerDashboardGraphChannel dashboardGraphChannel; + + if(!this->visualizer) return dashboardGraphChannel; + if(!this->visualizer->handshake) return dashboardGraphChannel; + if(this->plotCount == 0) return dashboardGraphChannel; + + this->plotCount--; + + uint16_t streamId = this->visualizer->index++; + + dashboardGraphChannel.visualizer = this->visualizer; + dashboardGraphChannel.id = streamId; + + MsgConfigStream msgConfigStream; + msgConfigStream.streamId = streamId; + msgConfigStream.type = STREAM_INT_32; + msgConfigStream.mode = STREAM_OUT; + msgConfigStream.state = STREAM_ON; + this->visualizer->protocol.configureStream(&msgConfigStream, text); + + MsgConfigAddStreamToElement msgConfigAddStreamToElement; + msgConfigAddStreamToElement.dashboardId = this->dashboard->id; + msgConfigAddStreamToElement.elementId = this->id; + msgConfigAddStreamToElement.streamId = streamId; + this->visualizer->protocol.addStreamToElement(&msgConfigAddStreamToElement); + + return dashboardGraphChannel; +} \ No newline at end of file diff --git a/src/DataVisualizerDashboardGraph.h b/src/DataVisualizerDashboardGraph.h new file mode 100644 index 0000000..ef28656 --- /dev/null +++ b/src/DataVisualizerDashboardGraph.h @@ -0,0 +1,25 @@ +#ifndef DATA_VISUALIZER_DASHBOARD_GRAPH_H +#define DATA_VISUALIZER_DASHBOARD_GRAPH_H + +#include "DataVisualizer.h" + +class DataVisualizer; +class DataVisualizerDashboard; +class DataVisualizerDashboardGraphChannel; +class DataVisualizerDashboardGraph { + friend class DataVisualizerDashboard; + + private: + uint16_t id; + uint8_t plotCount; + DataVisualizer* visualizer; + DataVisualizerDashboard *dashboard; + + public: + DataVisualizerDashboardGraph(void); + DataVisualizerDashboardGraphChannel addChannel(const char* text); +}; + +typedef DataVisualizerDashboardGraph DashboardGraph; + +#endif /* DATA_VISUALIZER_DASHBOARD_GRAPH_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboardGraphChannel.cpp b/src/DataVisualizerDashboardGraphChannel.cpp new file mode 100644 index 0000000..0946bb6 --- /dev/null +++ b/src/DataVisualizerDashboardGraphChannel.cpp @@ -0,0 +1,13 @@ +#include "DataVisualizerDashboardGraphChannel.h" + +DataVisualizerDashboardGraphChannel::DataVisualizerDashboardGraphChannel(void) { + this->id = 0; + this->visualizer = 0; +} + +void DataVisualizerDashboardGraphChannel::write(int32_t value) { + if(!this->visualizer) return; + if(!this->visualizer->handshake) return; + + this->visualizer->write(this->id, (uint8_t*) &value, sizeof(int32_t)); +} \ No newline at end of file diff --git a/src/DataVisualizerDashboardGraphChannel.h b/src/DataVisualizerDashboardGraphChannel.h new file mode 100644 index 0000000..ddae0da --- /dev/null +++ b/src/DataVisualizerDashboardGraphChannel.h @@ -0,0 +1,21 @@ +#ifndef DATA_VISUALIZER_DASHBOARD_GRAPH_CHANNEL_H +#define DATA_VISUALIZER_DASHBOARD_GRAPH_CHANNEL_H + +#include "DataVisualizer.h" + +class DataVisualizer; +class DataVisualizerDashboardGraphChannel { + friend class DataVisualizerDashboardGraph; + + private: + uint16_t id; + DataVisualizer* visualizer; + + public: + DataVisualizerDashboardGraphChannel(void); + void write(int32_t value); +}; + +typedef DataVisualizerDashboardGraphChannel DashboardGraphChannel; + +#endif /* DATA_VISUALIZER_DASHBOARD_GRAPH_CHANNEL_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboardLabel.cpp b/src/DataVisualizerDashboardLabel.cpp new file mode 100644 index 0000000..7295c0f --- /dev/null +++ b/src/DataVisualizerDashboardLabel.cpp @@ -0,0 +1,6 @@ +#include "DataVisualizerDashboardLabel.h" + +DataVisualizerDashboardLabel::DataVisualizerDashboardLabel(void) { + this->id = 0; + this->visualizer = 0; +} \ No newline at end of file diff --git a/src/DataVisualizerDashboardLabel.h b/src/DataVisualizerDashboardLabel.h new file mode 100644 index 0000000..2a54d57 --- /dev/null +++ b/src/DataVisualizerDashboardLabel.h @@ -0,0 +1,20 @@ +#ifndef DATA_VISUALIZER_DASHBOARD_LABEL_H +#define DATA_VISUALIZER_DASHBOARD_LABEL_H + +#include "DataVisualizer.h" + +class DataVisualizer; +class DataVisualizerDashboardLabel { + friend class DataVisualizerDashboard; + + private: + uint16_t id; + DataVisualizer* visualizer; + + public: + DataVisualizerDashboardLabel(void); +}; + +typedef DataVisualizerDashboardLabel DashboardLabel; + +#endif /* DATA_VISUALIZER_DASHBOARD_LABEL_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboardNumericInput.cpp b/src/DataVisualizerDashboardNumericInput.cpp new file mode 100644 index 0000000..828ca89 --- /dev/null +++ b/src/DataVisualizerDashboardNumericInput.cpp @@ -0,0 +1,29 @@ +#include "DataVisualizerDashboardNumericInput.h" + +DataVisualizerDashboardNumericInput::DataVisualizerDashboardNumericInput(void) { + this->id = 0; + this->visualizer = 0; + this->packet = 0; +} + +int32_t DataVisualizerDashboardNumericInput::read(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + int32_t value; + memcpy(&value, this->packet->data, LENGTH_4_BYTE); + return value; +} + +bool DataVisualizerDashboardNumericInput::feed(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + if(this->packet->sent) { + this->packet->sent = 0; + + return true; + } + + return false; +} diff --git a/src/DataVisualizerDashboardNumericInput.h b/src/DataVisualizerDashboardNumericInput.h new file mode 100644 index 0000000..3328983 --- /dev/null +++ b/src/DataVisualizerDashboardNumericInput.h @@ -0,0 +1,24 @@ +#ifndef DATA_VISUALIZER_DASHBOARD_NUMERIC_INPUT_H +#define DATA_VISUALIZER_DASHBOARD_NUMERIC_INPUT_H + +#include "DataVisualizer.h" + +struct DataPacket; +class DataVisualizer; +class DataVisualizerDashboardNumericInput { + friend class DataVisualizerDashboard; + + private: + uint16_t id; + DataPacket* packet; + DataVisualizer* visualizer; + + public: + DataVisualizerDashboardNumericInput(void); + int32_t read(void); + bool feed(void); +}; + +typedef DataVisualizerDashboardNumericInput DashboardNumericInput; + +#endif /* DATA_VISUALIZER_DASHBOARD_NUMERIC_INPUT_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboardRadioGroup.cpp b/src/DataVisualizerDashboardRadioGroup.cpp new file mode 100644 index 0000000..4816443 --- /dev/null +++ b/src/DataVisualizerDashboardRadioGroup.cpp @@ -0,0 +1,27 @@ +#include "DataVisualizerDashboardRadioGroup.h" + +DataVisualizerDashboardRadioGroup::DataVisualizerDashboardRadioGroup(void) { + this->id = 0; + this->visualizer = 0; + this->packet = 0; +} + +uint8_t DataVisualizerDashboardRadioGroup::selected(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + return this->packet->data[0]; +} + +bool DataVisualizerDashboardRadioGroup::feed(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + if(this->packet->sent) { + this->packet->sent = 0; + + return true; + } + + return false; +} diff --git a/src/DataVisualizerDashboardRadioGroup.h b/src/DataVisualizerDashboardRadioGroup.h new file mode 100644 index 0000000..dd00289 --- /dev/null +++ b/src/DataVisualizerDashboardRadioGroup.h @@ -0,0 +1,23 @@ +#ifndef DATA_VISUALIZER_DASHBOARD_RADIO_GROUP_H +#define DATA_VISUALIZER_DASHBOARD_RADIO_GROUP_H + +#include "DataVisualizer.h" + +class DataVisualizer; +class DataVisualizerDashboardRadioGroup { + friend class DataVisualizerDashboard; + + private: + uint16_t id; + DataPacket* packet; + DataVisualizer* visualizer; + + public: + DataVisualizerDashboardRadioGroup(void); + uint8_t selected(void); + bool feed(void); +}; + +typedef DataVisualizerDashboardRadioGroup DashboardRadioGroup; + +#endif /* DATA_VISUALIZER_DASHBOARD_RADIO_GROUP_H */ \ No newline at end of file diff --git a/src/DataVisualizerDashboardSignal.cpp b/src/DataVisualizerDashboardSignal.cpp new file mode 100644 index 0000000..c4d5fc3 --- /dev/null +++ b/src/DataVisualizerDashboardSignal.cpp @@ -0,0 +1,26 @@ +#include "DataVisualizerDashboardSignal.h" + +DataVisualizerDashboardSignal::DataVisualizerDashboardSignal(void) { + this->id = 0; + this->visualizer = 0; +} + +void DataVisualizerDashboardSignal::on(void) { + if(!this->visualizer) return; + if(!this->visualizer->handshake) return; + + uint8_t value = 1; + this->visualizer->write(this->id, (uint8_t*) &value, 1); + + /* this->visualizer->write(this->id, (uint8_t*) true, 1);*/ +} + +void DataVisualizerDashboardSignal::off(void) { + if(!this->visualizer) return; + if(!this->visualizer->handshake) return; + + uint8_t value = 0; + this->visualizer->write(this->id, (uint8_t*) &value, 1); + + /* this->visualizer->write(this->id, (uint8_t*) false, 1);*/ +} \ No newline at end of file diff --git a/src/DataVisualizerDashboardSignal.h b/src/DataVisualizerDashboardSignal.h new file mode 100644 index 0000000..eddaa44 --- /dev/null +++ b/src/DataVisualizerDashboardSignal.h @@ -0,0 +1,24 @@ +#ifndef DATAV_ISUALIZER_DASHBOARD_SIGNAL_H +#define DATAV_ISUALIZER_DASHBOARD_SIGNAL_H + +#include "DataVisualizer.h" + +class DataVisualizer; +class DataVisualizerDashboardSignal { + friend class DataVisualizerDashboard; + + private: + uint16_t id; + DataVisualizer* visualizer; + + public: + DataVisualizerDashboardSignal(void); + void on(void); + void off(void); +}; + +typedef DataVisualizerDashboardSignal DashboardSignal; + + + +#endif /* DATAV_ISUALIZER_DASHBOARD_SIGNAL_H */ \ No newline at end of file diff --git a/src/DataVisualizerGraph.cpp b/src/DataVisualizerGraph.cpp new file mode 100644 index 0000000..ad21923 --- /dev/null +++ b/src/DataVisualizerGraph.cpp @@ -0,0 +1,39 @@ +#include "DataVisualizerGraph.h" + +DataVisualizerGraph::DataVisualizerGraph(void) { + this->id = 0; + this->visualizer = 0; +} + +DataVisualizerGraphAxis DataVisualizerGraph::addAxis(const char *title) { + return this->addAxis(title, COLOR_RED, DEFAULT_GRAPH_MIN, DEFAULT_GRAPH_MAX); +} + +DataVisualizerGraphAxis DataVisualizerGraph::addAxis(const char *title, RgbColor color) { + return this->addAxis(title, color, DEFAULT_GRAPH_MIN, DEFAULT_GRAPH_MAX); +} + +DataVisualizerGraphAxis DataVisualizerGraph::addAxis(const char *title, RgbColor color, int32_t yMin, int32_t yMax) { + DataVisualizerGraphAxis axis; + + if(!this->visualizer) return axis; + if(!this->visualizer->handshake) return axis; + + uint16_t axisId = this->visualizer->index++; + axis.visualizer = this->visualizer; + axis.graph = this; + axis.id = axisId; + + MsgConfigAxis msgConfigAxis; + this->visualizer->protocol.addAxisToGraphGetDefaults(&msgConfigAxis); + msgConfigAxis.graphId = this->id; + msgConfigAxis.axisId = axisId; + msgConfigAxis.yMin = yMin; + msgConfigAxis.yMax = yMax; + msgConfigAxis.xScaleNumerator = 1; + msgConfigAxis.xScaleDenominator = 1; + this->visualizer->protocol.setColor(msgConfigAxis.color, color); + this->visualizer->protocol.addAxisToGraph(&msgConfigAxis, title); + + return axis; +} \ No newline at end of file diff --git a/src/DataVisualizerGraph.h b/src/DataVisualizerGraph.h new file mode 100644 index 0000000..966ea0f --- /dev/null +++ b/src/DataVisualizerGraph.h @@ -0,0 +1,28 @@ +#ifndef DATA_VISUALIZER_GRAPH_H +#define DATA_VISUALIZER_GRAPH_H + +#include "DataVisualizer.h" + +#define DEFAULT_GRAPH_MIN -32767 +#define DEFAULT_GRAPH_MAX +32767 + +class DataVisualizer; +class DataVisualizerGraphAxis; +class DataVisualizerGraph { + friend class DataVisualizer; + friend class DataVisualizerGraphAxis; + + private: + uint16_t id; + DataVisualizer* visualizer; + + public: + DataVisualizerGraph(void); + DataVisualizerGraphAxis addAxis(const char *title); + DataVisualizerGraphAxis addAxis(const char *title, RgbColor color); + DataVisualizerGraphAxis addAxis(const char *title, RgbColor color, int32_t yMin, int32_t yMax); +}; + +typedef DataVisualizerGraph Graph; + +#endif /* DATA_VISUALIZER_GRAPH_H */ \ No newline at end of file diff --git a/src/DataVisualizerGraphAxis.cpp b/src/DataVisualizerGraphAxis.cpp new file mode 100644 index 0000000..1e2143c --- /dev/null +++ b/src/DataVisualizerGraphAxis.cpp @@ -0,0 +1,76 @@ +#include "DataVisualizerGraphAxis.h" + +DataVisualizerGraphAxis::DataVisualizerGraphAxis(void) { + this->id = 0; + this->visualizer = 0; + this->graph = 0; +} + +DataVisualizerGraphAxisChannel DataVisualizerGraphAxis::addChannel(const char *label) { + return this->addChannel(label, COLOR_RED); +} + +DataVisualizerGraphAxisChannel DataVisualizerGraphAxis::addChannel(const char *label, RgbColor color) { + DataVisualizerGraphAxisChannel channel; + + if(!this->visualizer) return channel; + if(!this->visualizer->handshake) return channel; + + uint16_t streamId = this->visualizer->index++; + channel.visualizer = this->visualizer; + channel.id = streamId; + + MsgConfigStream msgConfigStream; + this->visualizer->protocol.configureStreamGetDefaults(&msgConfigStream); + msgConfigStream.streamId = streamId; + msgConfigStream.type = STREAM_INT_32; + msgConfigStream.mode = STREAM_OUT; + msgConfigStream.state = STREAM_ON; + this->visualizer->protocol.configureStream(&msgConfigStream, label); + + MsgAddStreamToAxis msgAddStreamToAxis; + this->visualizer->protocol.addStreamToAxisGetDefaults(&msgAddStreamToAxis); + msgAddStreamToAxis.graphId = this->graph->id; + msgAddStreamToAxis.axisId = this->id; + msgAddStreamToAxis.streamId = streamId; + this->visualizer->protocol.setColor(msgAddStreamToAxis.lineColor, color); + this->visualizer->protocol.addStreamToAxis(&msgAddStreamToAxis); + + return channel; +} + +DataVisualizerGraphAxisCursor DataVisualizerGraphAxis::addCursor(const char *label) { + return this->addCursor(label, COLOR_GREEN); +} + +DataVisualizerGraphAxisCursor DataVisualizerGraphAxis::addCursor(const char *label, RgbColor color) { + DataVisualizerGraphAxisCursor cursor; + + if(!this->visualizer) return cursor; + if(!this->visualizer->handshake) return cursor; + + uint16_t streamId = this->visualizer->index++; + cursor.visualizer = this->visualizer; + cursor.id = streamId; + cursor.packet = this->visualizer->pack(streamId, LENGTH_4_BYTE); + + MsgConfigStream msgConfigStream; + this->visualizer->protocol.configureStreamGetDefaults(&msgConfigStream); + msgConfigStream.streamId = streamId; + msgConfigStream.type = STREAM_INT_32; + msgConfigStream.mode = STREAM_IN; + msgConfigStream.state = STREAM_ON; + this->visualizer->protocol.configureStream(&msgConfigStream, label); + + MsgAddCursorToGraph msgAddCursorToGraph; + this->visualizer->protocol.addCursorToGraphGetDefaults(&msgAddCursorToGraph); + msgAddCursorToGraph.streamId = streamId; + msgAddCursorToGraph.graphId = this->graph->id; + msgAddCursorToGraph.axisId = this->id; + msgAddCursorToGraph.scaleNumerator = 1; + msgAddCursorToGraph.scaleDenominator = 1; + this->visualizer->protocol.setColor(msgAddCursorToGraph.color, color); + this->visualizer->protocol.addCursorToGraph(&msgAddCursorToGraph, label); + + return cursor; +} \ No newline at end of file diff --git a/src/DataVisualizerGraphAxis.h b/src/DataVisualizerGraphAxis.h new file mode 100644 index 0000000..6549f00 --- /dev/null +++ b/src/DataVisualizerGraphAxis.h @@ -0,0 +1,29 @@ +#ifndef DATA_VISUALIZER_GRAPH_AXIS_H +#define DATA_VISUALIZER_GRAPH_AXIS_H + +#include "DataVisualizer.h" + +class DataVisualizer; +class DataVisualizerGraph; +class DataVisualizerGraphAxisChannel; +class DataVisualizerGraphAxisCursor; +class DataVisualizerGraphAxis { + friend class DataVisualizer; + friend class DataVisualizerGraph; + + private: + uint16_t id; + DataVisualizer* visualizer; + DataVisualizerGraph* graph; + + public: + DataVisualizerGraphAxis(void); + DataVisualizerGraphAxisChannel addChannel(const char *label); + DataVisualizerGraphAxisChannel addChannel(const char *label, RgbColor color); + DataVisualizerGraphAxisCursor addCursor(const char *label); + DataVisualizerGraphAxisCursor addCursor(const char *label, RgbColor color); +}; + +typedef DataVisualizerGraphAxis GraphAxis; + +#endif /* DATA_VISUALIZER_GRAPH_AXIS_H */ \ No newline at end of file diff --git a/src/DataVisualizerGraphAxisChannel.cpp b/src/DataVisualizerGraphAxisChannel.cpp new file mode 100644 index 0000000..1da2a32 --- /dev/null +++ b/src/DataVisualizerGraphAxisChannel.cpp @@ -0,0 +1,13 @@ +#include "DataVisualizerGraphAxisChannel.h" + +DataVisualizerGraphAxisChannel::DataVisualizerGraphAxisChannel(void) { + this->id = 0; + this->visualizer = 0; +} + +void DataVisualizerGraphAxisChannel::write(int32_t value) { + if(!this->visualizer) return; + if(!this->visualizer->handshake) return; + + this->visualizer->write(this->id, (uint8_t*) &value, sizeof(int32_t)); +} \ No newline at end of file diff --git a/src/DataVisualizerGraphAxisChannel.h b/src/DataVisualizerGraphAxisChannel.h new file mode 100644 index 0000000..7b3cc26 --- /dev/null +++ b/src/DataVisualizerGraphAxisChannel.h @@ -0,0 +1,22 @@ +#ifndef DATA_VISUALIZER_GRAPH_AXIS_CHANNEL_H +#define DATA_VISUALIZER_GRAPH_AXIS_CHANNEL_H + +#include "DataVisualizer.h" + +class DataVisualizer; +class DataVisualizerGraphAxisChannel { + friend class DataVisualizer; + friend class DataVisualizerGraphAxis; + + private: + uint16_t id; + DataVisualizer* visualizer; + + public: + DataVisualizerGraphAxisChannel(void); + void write(int32_t value); +}; + +typedef DataVisualizerGraphAxisChannel GraphAxisChannel; + +#endif /* DATA_VISUALIZER_GRAPH_AXIS_CHANNEL_H */ \ No newline at end of file diff --git a/src/DataVisualizerGraphAxisCursor.cpp b/src/DataVisualizerGraphAxisCursor.cpp new file mode 100644 index 0000000..324dd59 --- /dev/null +++ b/src/DataVisualizerGraphAxisCursor.cpp @@ -0,0 +1,29 @@ +#include "DataVisualizerGraphAxisCursor.h" + +DataVisualizerGraphAxisCursor::DataVisualizerGraphAxisCursor(void) { + this->id = 0; + this->visualizer = 0; + this->packet = 0; +} + +int32_t DataVisualizerGraphAxisCursor::read(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + int32_t value; + memcpy(&value, this->packet->data, LENGTH_4_BYTE); + return value; +} + +bool DataVisualizerGraphAxisCursor::feed(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + if(this->packet->sent) { + this->packet->sent = 0; + + return true; + } + + return false; +} \ No newline at end of file diff --git a/src/DataVisualizerGraphAxisCursor.h b/src/DataVisualizerGraphAxisCursor.h new file mode 100644 index 0000000..d09fcde --- /dev/null +++ b/src/DataVisualizerGraphAxisCursor.h @@ -0,0 +1,25 @@ +#ifndef DATA_VISUALIZER_GRAPH_AXIS_CURSOR_H +#define DATA_VISUALIZER_GRAPH_AXIS_CURSOR_H + +#include "DataVisualizer.h" + +struct DataPacket; +class DataVisualizer; +class DataVisualizerGraphAxisCursor { + friend class DataVisualizer; + friend class DataVisualizerGraphAxis; + + private: + uint16_t id; + DataPacket* packet; + DataVisualizer* visualizer; + + public: + DataVisualizerGraphAxisCursor(void); + int32_t read(void); + bool feed(void); +}; + +typedef DataVisualizerGraphAxisCursor GraphAxisCursor; + +#endif /* DATA_VISUALIZER_GRAPH_AXIS_CURSOR_H */ \ No newline at end of file diff --git a/src/DataVisualizerTerminal.cpp b/src/DataVisualizerTerminal.cpp new file mode 100644 index 0000000..e3c7bcc --- /dev/null +++ b/src/DataVisualizerTerminal.cpp @@ -0,0 +1,93 @@ +#include "DataVisualizerTerminal.h" + +DataVisualizerTerminal::DataVisualizerTerminal(void) { + this->id = 0; + this->scan = 0; + this->visualizer = 0; + this->packet = 0; +} + +uint16_t DataVisualizerTerminal::available(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + return this->packet->sent; +} + +char DataVisualizerTerminal::read(void) { + if(!this->visualizer) return 0; + if(!this->visualizer->handshake) return 0; + + if(this->packet->sent) { + char value = packet->data[this->scan++]; + + if(this->scan == this->packet->sent) { + memset(this->packet->data, 0, this->packet->length); + this->scan = 0; + this->packet->sent = 0; + } + + return value; + } + + return 0; +} + +void DataVisualizerTerminal::read(char* buffer) { + if(!this->visualizer) return; + if(!this->visualizer->handshake) return; + + if(this->packet->sent) { + memcpy(buffer, this->packet->data, this->packet->sent); + memset(this->packet->data, 0, this->packet->length); + this->scan = 0; + this->packet->sent = 0; + } +} + +void DataVisualizerTerminal::print(char c) { + this->print(&c); +} + +void DataVisualizerTerminal::print(int n) { + this->print((long) n); +} + +void DataVisualizerTerminal::print(long n) { + char c[ITOA_MAX_LENGTH]; + itoa(n, c, ITOA_DEC); + this->print(c); +} + +void DataVisualizerTerminal::print(const char* c) { + if(!this->visualizer) return; + if(!this->visualizer->handshake) return; + + this->visualizer->write(this->id, (uint8_t*) c, strlen(c)); +} + +void DataVisualizerTerminal::println(char c) { + this->println(&c); +} + +void DataVisualizerTerminal::println(int n) { + this->println((long) n); +} + +void DataVisualizerTerminal::println(long n) { + char c[ITOA_MAX_LENGTH]; + itoa(n, c, ITOA_DEC); + this->println(c); +} + +void DataVisualizerTerminal::println(const char *c) { + if(!this->visualizer) return; + if(!this->visualizer->handshake) return; + + uint16_t length = strlen(c) + 1; + char data[length]; + strncpy(data, c, length - 1); + data[length - 1] = '\n'; + + this->visualizer->write(this->id, (uint8_t*) data, length); +} \ No newline at end of file diff --git a/src/DataVisualizerTerminal.h b/src/DataVisualizerTerminal.h new file mode 100644 index 0000000..f768b0b --- /dev/null +++ b/src/DataVisualizerTerminal.h @@ -0,0 +1,37 @@ +#ifndef DATA_VISUALIZER_TERMINAL_H +#define DATA_VISUALIZER_TERMINAL_H + +#include "DataVisualizer.h" + +#define ITOA_MAX_LENGTH 30 +#define ITOA_DEC 10 + +struct DataPacket; +class DataVisualizer; +class DataVisualizerTerminal { + friend class DataVisualizer; + + private: + uint16_t id; + uint16_t scan; + DataPacket* packet; + DataVisualizer* visualizer; + + public: + DataVisualizerTerminal(void); + uint16_t available(void); + void print(int n); + void print(long n); + void print(char c); + void print(const char *c); + void println(int n); + void println(long n); + void println(char c); + void println(const char *c); + char read(void); + void read(char* buffer); +}; + +typedef DataVisualizerTerminal Terminal; + +#endif /* DATA_VISUALIZER_TERMINAL_H */ \ No newline at end of file