This commit is contained in:
2026-07-21 17:20:06 +02:00
parent fc29c9c18a
commit f15aec39f5
3 changed files with 200 additions and 163 deletions
+19 -18
View File
@@ -9,36 +9,37 @@ enum ConMode_e {
}; };
enum IncommingCommands_e : uint16_t { enum IncommingCommands_e : uint16_t {
Qurey, // Qurey info Qurey = 0x00, // Qurey info
SetMaintanance, // Set Maintanance mode SetMaintanance = 0x01, // Set Maintanance mode
SetPromoMode, // Enable PromoMode SetPromoMode = 0x02, // Enable PromoMode
SetGamingMode, // Enable in Game mode SetGamingMode = 0x03, // Enable in Game mode
}; };
enum ServiceCommands_e { enum ServiceCommands_e {
Open, SerQuery = 0x10,
Close, Open = 0x11,
Play1, Close = 0x12,
Play2, Play1 = 0x13,
Play3, Play2 = 0x14,
Play3 = 0x15,
}; };
enum GameModeCommands_e { enum GameModeCommands_e {
GameNextTryLocked, // Lock sword on next try GameNextTryLocked = 0x21, // Lock sword on next try
GameNextTryRelease // Release sword on next try GameNextTryRelease = 0x22 // Release sword on next try
}; };
enum OutgoingCommands_e { enum OutgoingCommands_e {
Status, // Send Status Status = 0x00, // Send Status
Response, // Confirm last command Response = 0x01, // Confirm last command
Error, // Send error status Error = 0x02, // Send error status
PullHappend // Message if User tried to pull the sword PullHappend = 0x03 // Message if User tried to pull the sword
}; };
enum GameModeResponses_e { enum GameModeResponses_e {
SwordPullHappend, // Message if User tried to pull the sword SwordPullHappend = 0x11, // Message if User tried to pull the sword
SwordReleased, // Message that User pulled the sword SwordReleased = 0x12, // Message that User pulled the sword
SwordReturned // Message that User returned the sword SwordReturned = 0x13 // Message that User returned the sword
}; };
struct StatusFrame { struct StatusFrame {
+180 -144
View File
@@ -8,7 +8,7 @@ using namespace std::literals::chrono_literals;
using namespace std; using namespace std;
// using namespace std::literals; // using namespace std::literals;
const string BrockerUrl = "mqtts://nerdyssey.de:8883"; const string BrockerUrl = "mqtts://nerdyssey.de:8883";
const string MqttUser = "exodususer"; const string MqttUser = "exodususer";
const string MqttPassword = "awesomeexodusoutdooradventures"; const string MqttPassword = "awesomeexodusoutdooradventures";
@@ -167,7 +167,7 @@ void LoRaServiceTask(Thread::Context& ctx, Queue<RxMsg>& rxQueue, Queue<TxMsg>&
rxQueue.enqueue(std::move(e)); rxQueue.enqueue(std::move(e));
return true; return true;
}; };
auto spi = SpiPort({.mode = SpiPort::mode0, auto spi = SpiPort({.mode = SpiPort::Mode0,
.cs = SpiPort::Cs0, .cs = SpiPort::Cs0,
.frequ = 1'000'000}); .frequ = 1'000'000});
@@ -196,16 +196,30 @@ void LoRaServiceTask(Thread::Context& ctx, Queue<RxMsg>& rxQueue, Queue<TxMsg>&
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
fmt::println("Sword Firmware"); fmt::println("Sword Firmware");
if (argc > 1) {
fmt::println("Got Startup Argument");
auto arg1 = string{argv[1]};
if (arg1 == "promo") {
fmt::println("starting with promo");
Mode = OpMode::PromoMode;
} else if (arg1 == "game") {
fmt::println("starting with promo");
Mode = OpMode::PromoMode;
} else {
fmt::println("unknown {}", arg1);
}
}
auto itrHandler = [&]() { auto itrHandler = [&]() {
TriggeredInput itr(26, "PItr"); TriggeredInput itr(26, "PItr");
while (true) { while (true) {
std::cout << "Await next interrupt\n"; cout << "Await next interrupt\n";
if (itr.await()) { if (itr.await()) {
std::cout << "Interrupt Event\n"; cout << "Interrupt Event\n";
} }
} }
}; };
std::thread interruptThread(itrHandler); thread interruptThread(itrHandler);
InputPort spPort(SwordPulledPin, "PInSPull"); InputPort spPort(SwordPulledPin, "PInSPull");
InputPort sbPort(SwordEntryPin, "PinSEntry"); InputPort sbPort(SwordEntryPin, "PinSEntry");
@@ -227,159 +241,181 @@ int main(int argc, char* argv[]) {
static Queue<RxMsg> rxQueue; static Queue<RxMsg> rxQueue;
static Queue<TxMsg> txQueue; static Queue<TxMsg> txQueue;
static auto conTask = (ConMode == ModeMqtt) ? Thread::createExplicit("MqttTask", MQttServiceTask, std::ref(rxQueue), std::ref(txQueue)) static auto conTask = (ConMode == ModeMqtt) ? Thread::createExplicit("MqttTask", MQttServiceTask, ref(rxQueue), ref(txQueue))
: Thread::createExplicit("LoRaTask", LoRaServiceTask, std::ref(rxQueue), std::ref(txQueue)); : Thread::createExplicit("LoRaTask", LoRaServiceTask, ref(rxQueue), ref(txQueue));
SwordLatch.moveOut(); SwordLatch.moveOut();
const static map<IncommingCommands_e, OpMode> opCodes = {
{SetMaintanance, OpMode::Maintanance},
{SetPromoMode, OpMode::PromoMode},
{SetGamingMode, OpMode::GamingMode},
};
fmt::println("Running App"); fmt::println("Running App");
while (true) { while (true) {
auto msg = rxQueue.dequeue(); // auto msg = rxQueue.dequeue();
fmt::println("MAIN: Got message {}", msg->code); // fmt::println("MAIN: Got message {}", msg->code);
// auto code = static_cast<IncommingCommands_e>(msg->code);
// if (opCodes.contains(code)) {
// Mode == opCodes.at(code);
// } else {
// Mode = OpMode::Undefined;
// }
// fmt::println("running Maintanance");
// auto e = make_unique<ResponseTxMsg>(msg->code, 0);
// txQueue.enqueue(move(e));
auto code = static_cast<IncommingCommands_e>(msg->code); while (true) {
if (opCodes.contains(code)) { /* code */
Mode == opCodes.at(code);
} else {
Mode = OpMode::Undefined;
}
switch (Mode) { switch (Mode) {
case OpMode::Maintanance: { case OpMode::Maintanance: {
fmt::println("Got Maintanance"); fmt::println("Running Maintanance");
auto e = std::make_unique<ResponseTxMsg>(msg->code, 0); // txQueue.emplace<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e)); while (true) {
// txQueue.emplace<ResponseTxMsg>(msg->code, 0); auto serMsg = rxQueue.tryDequeueFor(1000ms);
if (serMsg) {
auto code = static_cast<ServiceCommands_e>(serMsg->code);
switch (code) {
case ServiceCommands_e::Open: {
IoStat->SwordLatch.moveIn();
} break;
case ServiceCommands_e::Close: {
IoStat->SwordLatch.moveOut();
} break;
case ServiceCommands_e::Play1: {
playWavFile(soundPromo);
} break;
case ServiceCommands_e::Play2: {
playWavFile(soundDeny);
} break;
case ServiceCommands_e::Play3: {
playWavFile(soundAllow);
} break;
}
}
tick();
auto e = make_unique<StatusTxMsg>(
(uint8_t)Mode,
IoStat->SwordEnd.get(),
IoStat->SwordEntry.get(),
IoStat->SwordPulled.get(),
IoStat->SwordLatch.isLocked());
txQueue.enqueue(move(e));
}
// auto e = make_unique<ResponseTxMsg>(msg->code, 0);
// txQueue.enqueue(move(e));
} break;
case OpMode::PromoMode: {
fmt::println("Running PromoMode");
auto tn = chrono::steady_clock::now();
while (true) {
auto serMsg = rxQueue.tryDequeueFor(10ms);
if (serMsg) {
auto code = static_cast<ServiceCommands_e>(serMsg->code);
switch (code) {
case ServiceCommands_e::Open: {
IoStat->SwordLatch.moveIn();
} break;
case ServiceCommands_e::Close: {
IoStat->SwordLatch.moveOut();
} break;
case ServiceCommands_e::Play1: {
playWavFile(soundPromo);
} break;
case ServiceCommands_e::Play2: {
playWavFile(soundDeny);
} break;
case ServiceCommands_e::Play3: {
playWavFile(soundAllow);
} break;
}
}
tick();
if (SwordPulled.isPosEdge()) {
playWavFile(soundPromo);
Thread::sleep(15s);
}
while (true) { if (chrono::steady_clock::now() > (tn + 1s)) {
auto serMsg = rxQueue.tryDequeueFor(1000ms); tn = chrono::steady_clock::now();
if (serMsg) { auto e = make_unique<StatusTxMsg>(
auto code = static_cast<ServiceCommands_e>(serMsg->code); (uint8_t)Mode,
IoStat->SwordEnd.get(),
IoStat->SwordEntry.get(),
IoStat->SwordPulled.get(),
IoStat->SwordLatch.isLocked());
txQueue.enqueue(move(e));
}
}
} break;
case OpMode::GamingMode: {
fmt::println("Running GamingMode");
while (true) {
auto gameMsg = rxQueue.dequeue();
auto code = static_cast<GameModeCommands_e>(gameMsg->code);
switch (code) { switch (code) {
case ServiceCommands_e::Open: { case GameModeCommands_e::GameNextTryLocked: {
IoStat->SwordLatch.moveIn(); auto e = make_unique<ResponseTxMsg>(gameMsg->code, 0);
txQueue.enqueue(move(e));
fmt::println("Got NextTryLock");
while (true) {
SwordPulled.sample();
auto rx = txQueue.tryDequeueFor(20ms);
bool pulled = SwordPulled.read();
if (SwordPulled.isPosEdge()) {
// say: You are not the one
Thread::sleep(5s);
}
}
} break; } break;
case ServiceCommands_e::Close: { case GameModeCommands_e::GameNextTryRelease: {
IoStat->SwordLatch.moveOut(); auto e = make_unique<ResponseTxMsg>(gameMsg->code, 0);
} break; txQueue.enqueue(move(e));
case ServiceCommands_e::Play1: { SwordLatch.moveIn();
playWavFile(soundPromo);
} break; fmt::println("Got NextTryRelease");
case ServiceCommands_e::Play2: { while (true) {
playWavFile(soundDeny); SwordEnd.sample();
} break; auto rx = txQueue.tryDequeueFor(20ms);
case ServiceCommands_e::Play3: { if (SwordEnd.isNegEdge()) {
playWavFile(soundAllow); break;
}
}
while (true) {
SwordEntry.sample();
auto rx = txQueue.tryDequeueFor(20ms);
if (SwordEntry.isNegEdge()) {
break;
}
}
// say: The prophecy is fulfilled
e = make_unique<ResponseTxMsg>(gameMsg->code, 0);
txQueue.enqueue(move(e));
while (true) {
SwordEnd.sample();
auto rx = txQueue.tryDequeueFor(20ms);
if (SwordEnd.isNegEdge()) {
break;
}
}
while (true) {
SwordEntry.sample();
auto rx = txQueue.tryDequeueFor(20ms);
if (SwordEntry.isNegEdge()) {
break;
}
}
e = make_unique<ResponseTxMsg>(gameMsg->code, 0);
txQueue.enqueue(move(e));
} break; } break;
} }
} }
} break;
auto e = std::make_unique<StatusTxMsg>( default:
(uint8_t)Mode, break;
IoStat->SwordEnd.get(), }
IoStat->SwordEntry.get(),
IoStat->SwordPulled.get(),
IoStat->SwordLatch.isLocked());
txQueue.enqueue(std::move(e));
}
e = std::make_unique<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e));
} break;
case OpMode::PromoMode: {
fmt::println("Got SetPromoMode");
auto e = std::make_unique<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e));
while (true) {
SwordPulled.sample();
auto rx = txQueue.tryDequeueFor(10ms);
if (SwordPulled.isPosEdge()) {
// say: Play our tours
Thread::sleep(5s);
}
}
} break;
case OpMode::GamingMode: {
fmt::println("Got SetGamingMode");
auto e = std::make_unique<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e));
while (true) {
auto gameMsg = txQueue.dequeue();
auto code = static_cast<GameModeCommands_e>(msg->code);
switch (code) {
case GameModeCommands_e::GameNextTryLocked: {
auto e = std::make_unique<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e));
fmt::println("Got NextTryLock");
while (true) {
SwordPulled.sample();
auto rx = txQueue.tryDequeueFor(20ms);
bool pulled = SwordPulled.read();
if (SwordPulled.isPosEdge()) {
// say: You are not the one
Thread::sleep(5s);
}
}
} break;
case GameModeCommands_e::GameNextTryRelease: {
auto e = std::make_unique<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e));
SwordLatch.moveIn();
fmt::println("Got NextTryRelease");
while (true) {
SwordEnd.sample();
auto rx = txQueue.tryDequeueFor(20ms);
if (SwordEnd.isNegEdge()) {
break;
}
}
while (true) {
SwordEntry.sample();
auto rx = txQueue.tryDequeueFor(20ms);
if (SwordEntry.isNegEdge()) {
break;
}
}
// say: The prophecy is fulfilled
e = std::make_unique<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e));
while (true) {
SwordEnd.sample();
auto rx = txQueue.tryDequeueFor(20ms);
if (SwordEnd.isNegEdge()) {
break;
}
}
while (true) {
SwordEntry.sample();
auto rx = txQueue.tryDequeueFor(20ms);
if (SwordEntry.isNegEdge()) {
break;
}
}
e = std::make_unique<ResponseTxMsg>(msg->code, 0);
txQueue.enqueue(std::move(e));
} break;
}
}
} break;
default:
break;
} }
} }
interruptThread.join(); interruptThread.join();