Files
BionxControl/bctransmitter.cpp

191 lines
5.0 KiB
C++
Raw Permalink Normal View History

2025-12-26 14:07:55 +01:00
/***************************************************************************
BionxControl
Copyright © 2025 christoph holzheuer
christoph.holzheuer@gmail.com
Using:
mhs_can_drv.c
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
Klaus Demlehner, klaus@mhs-elektronik.de
@see www.mhs-elektronik.de
Based on Bionx data type descriptions from:
BigXionFlasher USB V 0.2.4 rev. 97
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
@see www.bigxionflasher.org
Bionx Bike Info
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
@see www.ts-soft.de
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
@see https://github.com/bikemike/bionx-bikeinfo
***************************************************************************/
2025-12-20 16:33:00 +01:00
#include <QThread>
#include <QDebug>
#include <bctransmitter.h>
BCTransmitter::BCTransmitter(QObject *parent)
: QObject(parent), _isBusy(false)
{
2026-01-02 22:15:50 +01:00
//_canDriver = new BCDriverTinyCan{this};
_canDriver = new BCDriverDummy{this};
// forward driver state
connect( _canDriver, &BCDriver::driverStateChanged, this, &BCTransmitter::driverStateChanged );
2025-12-20 16:33:00 +01:00
}
void BCTransmitter::onToggleConnectionState( bool connect )
{
if( connect )
{
2026-01-01 23:01:31 +01:00
if( _canDriver->getDriverState() != BCDriver::DriverState::DeviceReady )
2025-12-30 14:42:49 +01:00
_canDriver->onStartDriver();
2025-12-20 16:33:00 +01:00
2026-01-01 01:58:54 +01:00
// __fix!
2026-01-02 16:25:21 +01:00
TransmitResult hwVersion = _canDriver->readRawByte( (uint32_t)BCDevice::ID::Console, (uint8_t)BC::ID::Cons_Rev_Hw);
2025-12-21 18:31:16 +01:00
if(!hwVersion)
2025-12-20 16:33:00 +01:00
{
qDebug() << "Console not responding";
}
else
{
2026-01-01 01:58:54 +01:00
2025-12-20 16:33:00 +01:00
}
2026-01-01 13:28:17 +01:00
qDebug() << " ---HAIL to the kings: " << hwVersion.value();
2025-12-20 16:33:00 +01:00
}
}
2026-01-02 16:25:21 +01:00
void BCTransmitter::enqueueValue( BCValuePtrConst value)
2025-12-20 16:33:00 +01:00
{
2026-01-02 01:43:49 +01:00
// Hier sind wir noch in GUI Thread
2025-12-20 16:33:00 +01:00
QMutexLocker locker(&_mutex);
_valueQueue.enqueue( value );
2025-12-20 16:33:00 +01:00
// wir wollen nicht den ganzen Value verschicken, erstrecht
2026-01-01 23:01:31 +01:00
// wollen wir nicht den Value in verschiedenen Threads gleichzeitig
2025-12-20 16:33:00 +01:00
// in die Hand nehmen, also hantieren wir nur mit den Inidizes.
// Trigger processing im Event-Loop des Worker Threads
// invokeMethod mit QueuedConnection entkoppelt den Aufruf,
2026-01-02 16:25:21 +01:00
// damit enqueueValue sofort zurückkehrt (non-blocking für den Aufrufer).
2025-12-20 16:33:00 +01:00
2026-01-02 22:15:50 +01:00
QMetaObject::invokeMethod(this, "processValue", Qt::QueuedConnection);
/*
2026-01-02 01:43:49 +01:00
QMetaObject::invokeMethod(this, [this]()
2025-12-20 16:33:00 +01:00
{
2026-01-02 16:25:21 +01:00
processValue();
2025-12-20 16:33:00 +01:00
}, Qt::QueuedConnection );
2026-01-02 22:15:50 +01:00
*/
2025-12-20 16:33:00 +01:00
}
2026-01-02 16:25:21 +01:00
void BCTransmitter::processValue()
2025-12-20 16:33:00 +01:00
{
if (_isBusy)
return;
_isBusy = true;
while (true)
{
2026-01-02 16:25:21 +01:00
BCValuePtrConst valuePtr{};
2025-12-20 16:33:00 +01:00
{
QMutexLocker locker(&_mutex);
if (_valueQueue.isEmpty())
{
_isBusy = false;
break; // Schleife verlassen, warten auf neue Events
}
2026-01-02 16:25:21 +01:00
valuePtr =_valueQueue.dequeue();
2025-12-20 16:33:00 +01:00
} // Mutex wird hier freigegeben! WICHTIG: Execute ohne Lock!
2026-01-02 16:25:21 +01:00
// Kosmetik
const BCValue& value = *(valuePtr.get());
2026-01-02 01:52:48 +01:00
2026-01-01 23:01:31 +01:00
// Value ist 'under construction'
2026-01-02 22:15:50 +01:00
//emit valueUpdated( value.deviceID, value.indexRow, BCValue::State::Locked );
2026-01-02 16:25:21 +01:00
2026-01-03 02:50:28 +01:00
2026-01-02 16:25:21 +01:00
uint32_t devID = static_cast<uint32_t>(value.deviceID);
uint8_t regID = static_cast<uint8_t> (value.registerID);
2026-01-02 22:15:50 +01:00
2026-01-02 16:25:21 +01:00
QString newVisibleValue;
2026-01-02 22:15:50 +01:00
BCValue::State newState = BCValue::State::NoState;
2026-01-02 16:25:21 +01:00
if(value.state.testFlag( BCValue::State::WriteMe ) )
{
2026-01-02 16:25:21 +01:00
}
2026-01-02 16:25:21 +01:00
// oder sollen wir hier beides erlauben ? readFlag & writeFlag ?
// Was kommt dann zuerst? Schreiben und lesen als verify ?
else if( value.state.testFlag( BCValue::State::ReadMe ) )
{
2026-01-02 16:25:21 +01:00
// wir sind hier im anderen thread! nicht einfach so reinschreiben, nur lesen
TransmitResult result = value.isWord ? readWordValue( devID, regID ) : readByteValue( devID, regID );
2026-01-02 16:25:21 +01:00
if( result.has_value() )
2026-01-02 22:15:50 +01:00
{
newVisibleValue = value.formatValue( result.value() );
2026-01-02 22:15:50 +01:00
newState = BCValue::State::InSync;
}
else
{
newState = BCValue::State::Failed;
}
}
2026-01-02 16:25:21 +01:00
2026-01-02 22:15:50 +01:00
emit valueUpdated( value.deviceID, value.indexRow, newState, newVisibleValue );
// __fix
2026-01-01 23:01:31 +01:00
bc::processEventsFor(50);
2025-12-28 22:48:18 +01:00
//emit valueStateChanged(cmd.id, true);
//emit valueStateChanged(0, true);
2025-12-20 16:33:00 +01:00
}
}
2026-01-01 23:01:31 +01:00
TransmitResult BCTransmitter::readByteValue( uint32_t deviceID, uint8_t registerID )
2026-01-02 16:25:21 +01:00
{
qDebug() << " --- YES: Read ByteValue: " << registerID;
// Wir lesen nur ein Byte und gut.
2026-01-02 16:25:21 +01:00
return _canDriver->readRawByte( deviceID, registerID );
2025-12-21 14:40:38 +01:00
}
2025-12-20 16:33:00 +01:00
2026-01-02 16:25:21 +01:00
TransmitResult BCTransmitter::readWordValue( uint32_t deviceID, uint8_t registerID )
2025-12-21 14:40:38 +01:00
{
qDebug() << " --- YES: Read WordValue: " << registerID;
uint32_t result{};
// hi byte Leseversuch.
TransmitResult value = _canDriver->readRawByte( deviceID, registerID );
// Fehler? dann weg
if( !value)
return std::unexpected( value.error() );
// hi byte speichern
result = *value << 8;
// low byte, liegt im followup register: +1
value = _canDriver->readRawByte( deviceID, registerID+1 );
if( !value)
return std::unexpected( value.error() );
result += *value;
return result;
2025-12-20 16:33:00 +01:00
}