diff --git a/VortexEngine/src/Menus/MenuList/EditorConnection.cpp b/VortexEngine/src/Menus/MenuList/EditorConnection.cpp index 09e44f8a5f..c22c52eeaa 100644 --- a/VortexEngine/src/Menus/MenuList/EditorConnection.cpp +++ b/VortexEngine/src/Menus/MenuList/EditorConnection.cpp @@ -188,6 +188,85 @@ Menu::MenuAction EditorConnection::run() SerialComs::write(EDITOR_VERB_TRANSMIT_VL_ACK); m_state = STATE_IDLE; break; + case STATE_PULL_EACH_MODE: + // editor requested pull modes, send the modes + m_receiveBuffer.clear(); + sendModeCount(); + m_state = STATE_PULL_EACH_MODE_COUNT; + break; + case STATE_PULL_EACH_MODE_COUNT: + if (receiveMessage(EDITOR_VERB_PULL_EACH_MODE_ACK)) { + if (Modes::numModes() == 0) { + m_state = STATE_IDLE; + } else { + m_previousModeIndex = Modes::curModeIndex(); + m_state = STATE_PULL_EACH_MODE_SEND; + } + } + break; + case STATE_PULL_EACH_MODE_SEND: + m_receiveBuffer.clear(); + // send the current mode + sendCurMode(); + // wait for the ack + m_state = STATE_PULL_EACH_MODE_WAIT; + break; + case STATE_PULL_EACH_MODE_WAIT: + // recive the ack from the editor to send next mode + if (receiveMessage(EDITOR_VERB_PULL_EACH_MODE_ACK)) { + // if there is still more modes + if (Modes::curModeIndex() < (Modes::numModes() - 1)) { + // then iterate to the next mode and send + Modes::nextMode(); + m_state = STATE_PULL_EACH_MODE_SEND; + } else { + // otherwise done sending modes + m_state = STATE_PULL_EACH_MODE_DONE; + } + } + break; + case STATE_PULL_EACH_MODE_DONE: + m_receiveBuffer.clear(); + // send our acknowledgement that the modes were sent + SerialComs::write(EDITOR_VERB_PULL_EACH_MODE_DONE); + // switch back to the previous mode + Modes::setCurMode(m_previousModeIndex); + // go idle + m_state = STATE_IDLE; + break; + case STATE_PUSH_EACH_MODE: + // editor requested to push modes, find out how many + m_receiveBuffer.clear(); + // ack the command and wait for the amount of modes + SerialComs::write(EDITOR_VERB_PUSH_EACH_MODE_ACK); + m_state = STATE_PUSH_EACH_MODE_COUNT; + break; + case STATE_PUSH_EACH_MODE_COUNT: + if (receiveModeCount()) { + // clear modes and start receiving + Modes::clearModes(); + m_state = STATE_PUSH_EACH_MODE_RECEIVE; + } + break; + case STATE_PUSH_EACH_MODE_RECEIVE: + // receive the modes into the receive buffer + if (receiveMode()) { + if (Modes::numModes() < m_numModesToReceive) { + // clear the receive buffer and ack the mode, continue receiving + m_receiveBuffer.clear(); + SerialComs::write(EDITOR_VERB_PUSH_EACH_MODE_ACK); + } else { + // success modes were received send the done + m_state = STATE_PUSH_EACH_MODE_DONE; + } + } + break; + case STATE_PUSH_EACH_MODE_DONE: + // say we are done + m_receiveBuffer.clear(); + SerialComs::write(EDITOR_VERB_PUSH_EACH_MODE_DONE); + m_state = STATE_IDLE; + break; } return MENU_CONTINUE; } @@ -269,6 +348,28 @@ void EditorConnection::sendModes() SerialComs::write(modesBuffer); } +void EditorConnection::sendModeCount() +{ + ByteStream buffer; + buffer.serialize8(Modes::numModes()); + SerialComs::write(buffer); +} + +void EditorConnection::sendCurMode() +{ + ByteStream modeBuffer; + Mode *cur = Modes::curMode(); + if (!cur) { + // ?? + return; + } + if (!cur->saveToBuffer(modeBuffer)) { + // ?? + return; + } + SerialComs::write(modeBuffer); +} + bool EditorConnection::receiveModes() { // need at least the buffer size first @@ -301,6 +402,42 @@ bool EditorConnection::receiveModes() return true; } +bool EditorConnection::receiveModeCount() +{ + // need at least the buffer size first + uint32_t size = 0; + if (m_receiveBuffer.size() < sizeof(size)) { + // wait, not enough data available yet + return false; + } + // grab the size out of the start + m_receiveBuffer.resetUnserializer(); + size = m_receiveBuffer.peek32(); + if (m_receiveBuffer.size() < (size + sizeof(size))) { + // don't unserialize yet, not ready + return false; + } + // okay unserialize now, first unserialize the size + if (!m_receiveBuffer.unserialize32(&size)) { + return false; + } + // create a new ByteStream that will hold the full buffer of data + ByteStream buf(m_receiveBuffer.rawSize()); + // then copy everything from the receive buffer into the rawdata + // which is going to overwrite the crc/size/flags of the ByteStream + memcpy(buf.rawData(), m_receiveBuffer.data() + sizeof(size), + m_receiveBuffer.size() - sizeof(size)); + // unserialize the mode count + if (!buf.unserialize8(&m_numModesToReceive)) { + return false; + } + if (m_numModesToReceive > MAX_MODES) { + return false; + } + // good mode count + return true; +} + bool EditorConnection::receiveDemoMode() { // need at least the buffer size first @@ -345,6 +482,10 @@ void EditorConnection::handleCommand() m_state = STATE_DEMO_MODE; } else if (receiveMessage(EDITOR_VERB_CLEAR_DEMO)) { m_state = STATE_CLEAR_DEMO; + } else if (receiveMessage(EDITOR_VERB_PULL_EACH_MODE)) { + m_state = STATE_PULL_EACH_MODE; + } else if (receiveMessage(EDITOR_VERB_PUSH_EACH_MODE)) { + m_state = STATE_PUSH_EACH_MODE; } else if (receiveMessage(EDITOR_VERB_TRANSMIT_VL)) { sendCurModeVL(); } diff --git a/VortexEngine/src/Menus/MenuList/EditorConnection.h b/VortexEngine/src/Menus/MenuList/EditorConnection.h index 5c49c01cb6..2a27d0601e 100644 --- a/VortexEngine/src/Menus/MenuList/EditorConnection.h +++ b/VortexEngine/src/Menus/MenuList/EditorConnection.h @@ -31,14 +31,18 @@ class EditorConnection : public Menu void showEditor(); void receiveData(); void sendModes(); + void sendModeCount(); + void sendCurMode(); bool receiveModes(); + bool receiveModeCount(); + bool receiveMode(); bool receiveDemoMode(); void handleCommand(); bool receiveMessage(const char *message); void clearDemo(); enum EditorConnectionState { - // the editor is not connec + // the editor is not connected STATE_DISCONNECTED, // Sending the greeting message @@ -47,27 +51,41 @@ class EditorConnection : public Menu // entirely idle, waiting for commands STATE_IDLE, - // engine pulls the modes from gloves, then wait for the sent modes ack + // editor pulls the modes from device, then wait for the sent modes ack STATE_PULL_MODES, STATE_PULL_MODES_SEND, STATE_PULL_MODES_DONE, - // engine pushes modes to gloves, then waits for done + // editor pushes modes to device, then waits for done STATE_PUSH_MODES, STATE_PUSH_MODES_RECEIVE, STATE_PUSH_MODES_DONE, - // engine pushes mode to gloves for demo while idle + // editor pushes mode to device for demo while idle STATE_DEMO_MODE, STATE_DEMO_MODE_RECEIVE, STATE_DEMO_MODE_DONE, - // engine tells gloves to clear the demo preview, gloves acknowledge + // editor tells device to clear the demo preview, device acknowledge STATE_CLEAR_DEMO, // transmit the mode over visible light STATE_TRANSMIT_MODE_VL, STATE_TRANSMIT_MODE_VL_DONE, + + // editor pulls the modes from device (safer version) + STATE_PULL_EACH_MODE, + STATE_PULL_EACH_MODE_COUNT, + STATE_PULL_EACH_MODE_SEND, + STATE_PULL_EACH_MODE_WAIT, + STATE_PULL_EACH_MODE_DONE, + + // editor pushes modes to device (safer version) + STATE_PUSH_EACH_MODE, + STATE_PUSH_EACH_MODE_COUNT, + STATE_PUSH_EACH_MODE_RECEIVE, + STATE_PULL_EACH_MODE_WAIT, + STATE_PUSH_EACH_MODE_DONE, }; // state of the editor @@ -76,6 +94,10 @@ class EditorConnection : public Menu ByteStream m_receiveBuffer; // Whether at least one command has been received yet bool m_allowReset; + // the mode index to return to after iterating the modes to send them + uint8_t m_previousModeIndex; + // the number of modes that should be received + uint8_t m_numModesToReceive; }; #endif diff --git a/VortexEngine/src/VortexConfig.h b/VortexEngine/src/VortexConfig.h index 9fafedd1f9..a10506b34e 100644 --- a/VortexEngine/src/VortexConfig.h +++ b/VortexEngine/src/VortexConfig.h @@ -430,52 +430,70 @@ // They are defined here so the editor can access them easily, // also so you can configure them at your own free will. -// the initial hello from the gloveset to the editor +// the initial hello from the device to the editor // is the full name of this build of vortex -#define EDITOR_VERB_GREETING_PREFIX "== " -#define EDITOR_VERB_GREETING_POSTFIX " ==" -#define EDITOR_VERB_GREETING EDITOR_VERB_GREETING_PREFIX VORTEX_FULL_NAME EDITOR_VERB_GREETING_POSTFIX +#define EDITOR_VERB_GREETING_PREFIX "== " +#define EDITOR_VERB_GREETING_POSTFIX " ==" +#define EDITOR_VERB_GREETING EDITOR_VERB_GREETING_PREFIX VORTEX_FULL_NAME EDITOR_VERB_GREETING_POSTFIX -// the hello from the editor to the gloves -#define EDITOR_VERB_HELLO "a" +// the hello from the editor to the device +#define EDITOR_VERB_HELLO "a" -// the response from the gloveset when it's ready to receive something -// after the editor has given it a command to do something the gloveset +// the response from the device when it's ready to receive something +// after the editor has given it a command to do something the device // will respond with this then once it's done doing the action it will // send a different finished response for each action -#define EDITOR_VERB_READY "b" +#define EDITOR_VERB_READY "b" +// =============================================================================== +// TODO: remove the below commands once they are no longer used +// these commands can sometimes cause crashes if the modes list is too big // the command from the editor to send modes over -#define EDITOR_VERB_PULL_MODES "c" +#define EDITOR_VERB_PULL_MODES "c" // the response from the editor once modes are received -#define EDITOR_VERB_PULL_MODES_DONE "d" -// the response from the gloves once it acknowledges the editor got the modes -#define EDITOR_VERB_PULL_MODES_ACK "e" - +#define EDITOR_VERB_PULL_MODES_DONE "d" +// the response from the device once it acknowledges the editor got the modes +#define EDITOR_VERB_PULL_MODES_ACK "e" // the command from the editor to send modes over -#define EDITOR_VERB_PUSH_MODES "f" -// the response from the gloveset when it received the mode -#define EDITOR_VERB_PUSH_MODES_ACK "g" - -// the command from the editor to tell the gloveset to demo a mode -#define EDITOR_VERB_DEMO_MODE "h" -// the response from the gloveset when it's received the mode to demo -#define EDITOR_VERB_DEMO_MODE_ACK "i" - -// the command from the editor to tell the gloveset to clear the demo -#define EDITOR_VERB_CLEAR_DEMO "j" -// the response from the gloveset when it's received disabled the demo -#define EDITOR_VERB_CLEAR_DEMO_ACK "k" - -// when the gloveset is leaving the menu and needs to tell the editor +#define EDITOR_VERB_PUSH_MODES "f" +// the response from the device when it received the mode +#define EDITOR_VERB_PUSH_MODES_ACK "g" +// TODO: remove the above commands once they are no longer used +// =============================================================================== + +// the command from the editor to tell the device to demo a mode +#define EDITOR_VERB_DEMO_MODE "h" +// the response from the device when it's received the mode to demo +#define EDITOR_VERB_DEMO_MODE_ACK "i" + +// the command from the editor to tell the device to clear the demo +#define EDITOR_VERB_CLEAR_DEMO "j" +// the response from the device when it's received disabled the demo +#define EDITOR_VERB_CLEAR_DEMO_ACK "k" + +// when the device is leaving the menu and needs to tell the editor // that it's no longer listening -#define EDITOR_VERB_GOODBYE "l" +#define EDITOR_VERB_GOODBYE "l" // when the computer wants to send a mode to the duo it tells the device // to transmit over VL and send the current preview mode to the duo -#define EDITOR_VERB_TRANSMIT_VL "m" +#define EDITOR_VERB_TRANSMIT_VL "m" // the response from the device when it's done transmitting the mode -#define EDITOR_VERB_TRANSMIT_VL_ACK "n" +#define EDITOR_VERB_TRANSMIT_VL_ACK "n" + +// the command from the editor to send modes over +#define EDITOR_VERB_PULL_EACH_MODE "o" +// the response from the device when it acknowledges a command +#define EDITOR_VERB_PULL_EACH_MODE_ACK "p" +// the response from the editor once modes are received +#define EDITOR_VERB_PULL_EACH_MODE_DONE "q" + +// the command from the editor to send modes over +#define EDITOR_VERB_PUSH_EACH_MODE "r" +// the response from the device when it received the command +#define EDITOR_VERB_PUSH_EACH_MODE_ACK "s" +// the response from the device when it received the command +#define EDITOR_VERB_PUSH_EACH_MODE_DONE "t" // =================================================================== // Manually Configured Sizes diff --git a/VortexEngine/src/VortexEngine.cpp b/VortexEngine/src/VortexEngine.cpp index bfd51e3b1b..056115dd72 100644 --- a/VortexEngine/src/VortexEngine.cpp +++ b/VortexEngine/src/VortexEngine.cpp @@ -83,6 +83,8 @@ bool VortexEngine::init() return false; } + Menus::openMenu(MENU_EDITOR_CONNECTION); + #if COMPRESSION_TEST == 1 compressionTest(); #endif