// joypad.h ─────────────────────────────────────────────────────────── #pragma once #include #include #include // <- для AllocConsole #using using namespace System; using namespace System::IO::Ports; using namespace System::Threading; /*--------------------------------------------------------------------- Joypad (i-Bus → COM-порт) ---------------------------------------------------------------------*/ public ref class Joypad { public: /* событие – _не подписывайтесь_ ➜ ничего в форме не вызовется */ delegate void TickHandler(array^ ch); event TickHandler^ TickEvent; Joypad() { // -------- открываем консоль один раз ---------------------- static bool consoleReady = false; if (!consoleReady && ::AllocConsole()) { FILE* fp; freopen_s(&fp, "CONOUT$", "w", stdout); std::cout << " CH1 CH2 CH3 CH4 CH5 CH6\n"; consoleReady = true; } // ---------------------------------------------------------- _sp = gcnew SerialPort(); _sp->ReadTimeout = 200; _sp->ReadBufferSize = 256; } /* ---------- запуск ------------------------------------------- */ bool Start(String^ port, int baud ) { if (_run) return true; try { _sp->PortName = port; _sp->BaudRate = baud; _sp->Parity = Parity::None; _sp->DataBits = 8; _sp->StopBits = StopBits::One; _sp->Open(); } catch (Exception^ ex) { System::Diagnostics::Debug::WriteLine("Serial error: " + ex->Message); return false; } _run = true; _thr = gcnew Thread(gcnew ThreadStart(this, &Joypad::RxLoop)); _thr->IsBackground = true; _thr->Start(); return true; } /* ---------- остановка ---------------------------------------- */ void Stop() { _run = false; if (_thr && _thr->IsAlive) _thr->Join(); if (_sp->IsOpen) _sp->Close(); } property array^ Channels { array^ get() { return _ch; } } private: // ----------- поток приёма i-Bus --------------------------------- void RxLoop() { array^ buf = gcnew array(64); array^ pkt = gcnew array(32); while (_run) { int read = 0; try { read = _sp->Read(buf, 0, buf->Length); } catch (TimeoutException^) { continue; } for (int i = 0; i < read; ++i) { _fifo[_head++] = buf[i]; if (_head >= _fifo->Length) _head = 0; if (_fifo[_head] == 0x20 && _fifo[(_head + 1) & 0x7F] == 0x40) { for (int j = 0; j < 32; ++j) pkt[j] = _fifo[(_head + j) & 0x7F]; if (!CheckPkt(pkt)) continue; ParseChannels(pkt); // -------- 1) печать в консоль ---------------- std::cout << '\r'; for (int k = 0; k < 6; ++k) std::cout << std::setw(6) << _ch[k] << ' '; std::cout << std::flush; // --------------------------------------------- // -------- 2) необязательный вызов события ---- TickEvent(_ch); // raise } } } } bool CheckPkt(array^ p) { UInt16 sum = 0; for (int i = 0; i < 30; ++i) sum += p[i]; sum = 0xFFFF - sum; return sum == (p[30] | p[31] << 8); } void ParseChannels(array^ p) { for (int i = 0; i < 14; ++i) _ch[i] = (UInt16)(p[2 + i * 2] | p[3 + i * 2] << 8); } /* ---------- поля --------------------------------------------- */ SerialPort^ _sp; Thread^ _thr; bool _run = false; array^ _ch = gcnew array(14); array^ _fifo = gcnew array(128); int _head = 0; };