Graphic updates.

This commit is contained in:
2026-01-09 00:45:26 +01:00
parent d6da7aac9a
commit 95765226e9
9 changed files with 98 additions and 896 deletions

View File

@@ -45,7 +45,6 @@ windows
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
aalegacy.cpp \
bc.cpp \
bcanimateddelegate.cpp \
bcdeviceview.cpp \

View File

@@ -1,744 +0,0 @@
/* BigXionFlasher.c */
/* ====================================================================
* Copyright (c) 2011-2013 by Thomas König <info@bigxionflasher.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the
* BigXionFlasher Project. (http://www.bigxionflasher.org/)"
*
* 4. The name "BigXionFlasher" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* info@bigxionflasher.org.
*
* 5. Products derived from this software may not be called "BigXionFlasher"
* nor may "BigXionFlasher" appear in their names without prior written
* permission of the BigXionFlasher Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the
* BigXionFlasher Project. (http://www.bigxionflasher.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE BigXionFlasher PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE BigXionFlasher PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#ifdef __WIN32__
#include <conio.h>
#define DEVICE_OPEN NULL
#define TREIBER_NAME "mhstcan.dll"
#define _NL "\n\r"
#define _DEGREE_SIGN "o"
#else
#define DEVICE_OPEN NULL
#define TREIBER_NAME "libmhstcan.so"
#define _NL "\n"
#define _DEGREE_SIGN "°"
#endif
#include "can_drv.h"
#define __DOSTR(v) #v
#define __STR(v) __DOSTR(v)
#define __BXF_VERSION__ "V 0.2.4 rev. 97"
#define UNLIMITED_SPEED_VALUE 70 /* Km/h */
#define UNLIMITED_MIN_SPEED_VALUE 30 /* Km/h */
#define MAX_THROTTLE_SPEED_VALUE 70 /* Km/h */
//#include "registers.h"
#define TIMEOUT_VALUE 80
#define TIMEOUT_US 10000 // 10ms
#define BATTERY_REF_HW 1
#define BATTERY_REF_SW 1
#define BATTERY_SN_PN_HI 1
#define BATTERY_SN_PN_LO 1
#define BATTERY_SN_ITEM_HI 1
#define BATTERY_SN_ITEM_LO 1
#define BATTERY_STATUS_VBATT_HI 1
#define BATTERY_STATUS_VBATT_LO 1
#define BATTERY_STATUS_LEVEL 1
#define BATTERY_STATS_VBATTMAX 1
#define BATTERY_STATS_VBATTMIN 1
#define BATTERY_STATS_VBATTMEA 1
#define BATTERY_STATS_VBATTMEAN 1
#define BATTERY_STATS_RESET_HI 1
#define BATTERY_STATS_RESET_LO 1
#define BATTERY_STSTS_GGJSRCALIB 1
#define BATTERY_STSTS_VCTRLSHORTS 1
#define BATTERY_STATS_LMD_HI 1
#define BATTERY_STATS_LMD_LO 1
#define BATTERY_CONFIG_CELLCAPACITY_HI 1
#define BATTERY_CONFIG_CELLCAPACITY_LO 1
#define BATTERY_STATS_CHARGETIMEWORST_HI 1
#define BATTERY_STATS_CHARGETIMEWORST_LO 1
#define BATTERY_STATS_CHARGETIMEMEAN_HI 1
#define BATTERY_STATS_CHARGETIMEMEAN_LO 1
#define BATTERY_STATS_BATTCYCLES_HI 1
#define BATTERY_STATS_BATTCYCLES_LO 1
#define BATTERY_STATS_BATTFULLCYCLES_HI 1
#define BATTERY_STATS_BATTFULLCYCLES_LO 1
#define BATTERY_STATS_POWERCYCLES_HI 1
#define BATTERY_STATS_POWERCYCLES_LO 1
#define BATTERY_STATS_TBATTMAX 1
#define BATTERY_STATS_TBATTMIN 1
#define MOTOR_REF_HW 1
#define MOTOR_REF_SW 1
#define MOTOR_REALTIME_TEMP 1
#define MOTOR_SN_PN_HI 1
#define MOTOR_SN_PN_LO 1
#define MOTOR_SN_ITEM_HI 1
#define MOTOR_SN_ITEM_LO 1
#define CONSOLE_STATUS_SLAVE 1
#define BATTERY_CONFIG_SHUTDOWN 1
#define CONSOLE_ASSIST_MAXSPEEDFLAG 1
#define CONSOLE_ASSIST_MAXSPEED_HI 1
#define CONSOLE_ASSIST_MAXSPEED_LO 1
#define MOTOR_PROTECT_UNLOCK 1
#define MOTOR_PROTECT_UNLOCK_KEY 1
#define MOTOR_ASSIST_MAXSPEED 1
#define CONSOLE_GEOMETRY_CIRC_HI 1
#define CONSOLE_GEOMETRY_CIRC_LO1
#define CONSOLE_GEOMETRY_CIRC_LO 1
#define MOTOR_GEOMETRY_CIRC_HI1
#define MOTOR_GEOMETRY_CIRC_HI 1
#define MOTOR_GEOMETRY_CIRC_LO 1
#define CONSOLE_ASSIST_MINSPEEDFLAG 1
#define CONSOLE_ASSIST_MINSPEED 1
#define CONSOLE_THROTTLE_MAXSPEEDFLAG 1
#define CONSOLE_THROTTLE_MAXSPEED_HI 1
#define CONSOLE_THROTTLE_MAXSPEED_LO 1
#define BATTERY_CONFIG_PACKSERIAL 1
#define BATTERY_CELLMON_BALANCERENABLED 1
#define BATTERY_CONFIG_PACKPARALLEL 1
#define BATTERY_CELLMON_CHANNELADDR 1
#define BATTERY_CELLMON_CHANNELDATA_HI 1
#define BATTERY_STATUS_PACKTEMPERATURE1 1
#define BATTERY_CELLMON_CHANNELDATA_LO 1
#define CONSOLE_REF_HW 1
#define CONSOLE_REF_SW 1
#define CONSOLE_ASSIST_INITLEVEL 1
#define CONSOLE_SN_PN_HI 1
#define CONSOLE_SN_PN_LO 1
#define CONSOLE_SN_ITEM_HI 1
#define CONSOLE_SN_ITEM_LO 1
#define CONSOLE_ASSIST_MOUNTAINCAP 1
#define CONSOLE_STATS_BCValueTypeWord_1 1
#define CONSOLE_STATS_BCValueTypeWord_2 1
#define CONSOLE_STATS_BCValueTypeWord_3 1
#define CONSOLE_STATS_BCValueTypeWord_4 1
#define doSleep(x) usleep(x*1000)
int gAssistInitLevel = -1, gPrintSystemSettings = 0, gSkipShutdown = 0, gPowerOff = 0, gConsoleSetSlaveMode = 1, gNoSerialNumbers = 0, gSetMountainCap = -1, gSetWheelCircumference = 0;
double gSetSpeedLimit = -1, gSetMinSpeedLimit = -1, gSetThrottleSpeedLimit = -1;
#define CONSOLE 1
#define MOTOR 2
#define BATTERY 3
#define BIB 4
char *getNodeName(unsigned char id)
{
if (id == CONSOLE)
return "console";
else if (id == BATTERY)
return "battery";
else if (id == MOTOR)
return "motor";
else if (id == BIB)
return "bib";
else
return "UNKNOWN";
}
void setValue(unsigned char receipient, unsigned char reg, unsigned char value)
{
struct TCanMsg msg;
int timeout = TIMEOUT_VALUE;
msg.MsgFlags = 0L;
msg.Id = receipient;
msg.MsgLen = 4;
msg.MsgData[0] = 0x00;
msg.MsgData[1] = reg;
msg.MsgData[2] = 0x00;
msg.MsgData[3] = value;
CanTransmit(0, &msg, 1);
while(timeout-- && CanTransmitGetCount(0))
usleep(TIMEOUT_US);
if (timeout == -1)
printf("error: could not send value to %s" _NL, getNodeName(receipient));
}
unsigned int getValue(unsigned char receipient, unsigned char reg)
{
struct TCanMsg msg;
int err, retry = 20;
int timeout = TIMEOUT_VALUE;
msg.MsgFlags = 0L;
msg.Id = receipient;
msg.MsgLen = 2;
msg.MsgData[0] = 0x00;
msg.MsgData[1] = reg;
CanTransmit(0, &msg, 1);
while(timeout-- && CanTransmitGetCount(0))
usleep(TIMEOUT_US);
if (timeout == -1)
printf("error: could not send value to node %s" _NL, getNodeName(receipient));
retry:
timeout = TIMEOUT_VALUE;
while(timeout-- && !CanReceiveGetCount(0))
usleep(TIMEOUT_US);
if (timeout == -1)
{
printf("error: no response from node %s" _NL, getNodeName(receipient));
return 0;
}
if ((err = CanReceive(0, &msg, 1)) > 0)
{
if (--retry && (msg.Id != BIB || msg.MsgLen != 4 || msg.MsgData[1] != reg))
goto retry;
if (!retry)
{
printf("error: no response from node %s to %s" _NL, getNodeName(receipient), getNodeName(BIB));
return 0;
}
return (unsigned int) msg.MsgData[3];
}
else
{
printf("Error: %d" _NL, err);
}
return 0;
}
void setSpeedLimit(double speed)
{
int limit = (speed != 0);
if (!speed)
speed = UNLIMITED_SPEED_VALUE;
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEEDFLAG, limit);
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_HI, ((int)(speed * 10)) >> 8);
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_LO, ((int)(speed * 10)) & 0xff);
setValue(MOTOR, MOTOR_PROTECT_UNLOCK, MOTOR_PROTECT_UNLOCK_KEY);
setValue(MOTOR, MOTOR_ASSIST_MAXSPEED, (int)speed);
}
void setWheelCircumference(unsigned short circumference)
{
if (!circumference)
return;
setValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_HI, (int) (circumference >> 8));
setValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_LO, (int) (circumference & 0xff));
setValue(MOTOR, MOTOR_PROTECT_UNLOCK, MOTOR_PROTECT_UNLOCK_KEY);
setValue(MOTOR, MOTOR_GEOMETRY_CIRC_HI, (int) (circumference >> 8));
setValue(MOTOR, MOTOR_GEOMETRY_CIRC_LO, (int) (circumference & 0xff));
}
void setMinSpeedLimit(double speed)
{
char limit = (speed != 0);
setValue(CONSOLE, CONSOLE_ASSIST_MINSPEEDFLAG, limit);
setValue(CONSOLE, CONSOLE_ASSIST_MINSPEED, (int)(speed * 10));
}
void setThrottleSpeedLimit(double speed)
{
int limit = (speed != 0);
if (!speed)
speed = MAX_THROTTLE_SPEED_VALUE;
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEEDFLAG, limit);
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_HI, ((int)(speed * 10)) >> 8);
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_LO, ((int)(speed * 10)) & 0xff);
}
void printBatteryStats()
{
int channel = 1, packSerial, packParallel;
printf( " balancer enabled ...: %s" _NL _NL, (getValue(BATTERY, BATTERY_CELLMON_BALANCERENABLED != 0) ? "yes" : "no"));
packSerial = getValue(BATTERY, BATTERY_CONFIG_PACKSERIAL);
packParallel = getValue(BATTERY, BATTERY_CONFIG_PACKPARALLEL);
packSerial = (packSerial > 20) ? 0 : packSerial;
packParallel = (packParallel > 20) ? 0 : packParallel;
for (;channel <= packSerial; channel++) {
setValue(BATTERY, BATTERY_CELLMON_CHANNELADDR, (int)0x80 + channel);
printf(" voltage cell #%02d ...: %.3fV" _NL, channel,
((getValue(BATTERY, BATTERY_CELLMON_CHANNELDATA_HI) << 8) + getValue(BATTERY,BATTERY_CELLMON_CHANNELDATA_LO)) * 0.001);
}
for (channel = 0 ; channel < packParallel ; channel ++)
printf(" temperature pack #%02d: %d" _DEGREE_SIGN "C" _NL, channel + 1,
getValue(BATTERY, BATTERY_STATUS_PACKTEMPERATURE1 + channel));
printf(_NL);
}
void printChargeStats() {
int channel = 1, totalChagres = 0, c;
for (channel = 1 ; channel <= 10; channel++) {
setValue(BATTERY, 0xf6, channel);
c = (getValue(BATTERY, 0xf7) << 8) + getValue(BATTERY,0xf8);
totalChagres += c;
printf(" charge level @ %03d%% : %04d" _NL, channel*10, c);
}
printf(" total # of charges .: %04d" _NL _NL, totalChagres);
}
double getVoltageValue(unsigned char in, unsigned char reg)
{
return (getValue(BATTERY, reg) + 20.8333) * 0.416667;
}
void usage(void) {
printf( "usage:" _NL
" -l <speedLimit> .......... set the speed limit to <speedLimit> (1 - " __STR(UNLIMITED_SPEED_VALUE) "), 0 = remove the limit" _NL );
}
int parseOptions(int argc, char **argv)
{
int oc;
char odef[] = "l:t:m:sa:pnxio:c:h?";
while((oc = getopt(argc,argv,odef)) != -1) {
switch(oc) {
case 'p':
gPowerOff = 1;
break;
case 'x':
gSkipShutdown = 1;
break;
case 'l':
gSetSpeedLimit = atof(optarg);
if (gSetSpeedLimit > UNLIMITED_SPEED_VALUE || gSetSpeedLimit < 0) {
printf("error: speed limit %.2f is out of range. exiting..." _NL, gSetSpeedLimit);
return -1;
}
break;
case 't':
gSetThrottleSpeedLimit = atof(optarg);
if (gSetThrottleSpeedLimit > MAX_THROTTLE_SPEED_VALUE || gSetThrottleSpeedLimit < 0) {
printf("error: throttle speed limit %.2f is out of range. exiting..." _NL, gSetThrottleSpeedLimit);
return -1;
}
break;
case 'm':
gSetMinSpeedLimit = atof(optarg);
if (gSetMinSpeedLimit > UNLIMITED_MIN_SPEED_VALUE || gSetMinSpeedLimit < 0) {
printf("error: min speed limit %.2f is out of range. exiting..." _NL, gSetMinSpeedLimit);
return -1;
}
break;
case 'a':
gAssistInitLevel = atoi(optarg);
if (gAssistInitLevel > 4 || gAssistInitLevel < 0) {
printf("error: initial assist level %d is out of range. exiting..." _NL, gAssistInitLevel);
return -1;
}
break;
case 'o':
gSetMountainCap = atoi(optarg);
if (gSetMountainCap > 100 || gSetMountainCap < 0) {
printf("error: mountain cap level %d is out of range. exiting..." _NL, gSetMountainCap);
return -1;
}
break;
case 'c':
gSetWheelCircumference = atoi(optarg);
if (gSetWheelCircumference > 3000 || gSetWheelCircumference < 1000) {
printf("error: wheel circumference %d is out of range. exiting..." _NL, gSetWheelCircumference);
return -1;
}
break;
case 'n':
gConsoleSetSlaveMode = 0;
break;
case 'i':
gNoSerialNumbers = 1;
break;
case 's':
gPrintSystemSettings = 1;
break;
case 'h':
case '?':
default:
usage();
return -1;
}
}
return 0;
}
void printSystemSettings()
{
int hwVersion, swVersion, wheelCirc;
char *sl;
double speedLimit = 0;
printf(_NL _NL);
hwVersion = getValue(CONSOLE, CONSOLE_REF_HW);
if (hwVersion == 0)
printf("Console not responding" _NL _NL);
else {
swVersion = getValue(CONSOLE, CONSOLE_REF_SW);
printf( "Console information:" _NL
" hardware version ........: %02d" _NL
" software version ........: %02d" _NL
" assistance level ........: %d" _NL,
hwVersion, swVersion,
getValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL)
);
if (!gNoSerialNumbers)
printf( " part number .............: %05d" _NL
" item number .............: %05d" _NL _NL,
((getValue(CONSOLE, CONSOLE_SN_PN_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_PN_LO)),
((getValue(CONSOLE, CONSOLE_SN_ITEM_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_ITEM_LO))
);
/* ASSIST speed limit */
sl = getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
speedLimit = ((getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_HI) << 8) + getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_LO)) / (double)10;
printf( " max limit enabled .......: %s" _NL
" speed limit .............: %0.2f Km/h" _NL _NL, sl, speedLimit);
/* MIN speed limit */
sl = getValue(CONSOLE, CONSOLE_ASSIST_MINSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
speedLimit = (getValue(CONSOLE, CONSOLE_ASSIST_MINSPEED)) / (double)10;
printf( " min limit enabled .......: %s" _NL
" min speed limit .........: %0.2f Km/h" _NL _NL, sl, speedLimit);
/* THROTTLE speed limit */
sl = getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
speedLimit = ((getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_HI) << 8) + getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_LO)) / (double)10;
printf( " throttle limit enabled ..: %s" _NL
" throttle speed limit ....: %0.2f Km/h" _NL _NL, sl, speedLimit);
/* WHEEL CIRCUMFERENCE */
wheelCirc = (getValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_HI) << 8) + getValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_LO);
printf( " wheel circumference .....: %d mm" _NL _NL, wheelCirc);
if (swVersion >= 59)
printf(
" mountain cap ............: %0.2f%%" _NL,
(getValue(CONSOLE, CONSOLE_ASSIST_MOUNTAINCAP) * 1.5625));
printf( " odo .....................: %0.2f Km" _NL _NL,
((getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_1) << 24) +
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_2) << 16) +
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_3) << 8) +
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_4))) / (double)10
);
}
hwVersion = getValue(BATTERY, BATTERY_REF_HW);
if (hwVersion == 0)
printf("Battery not responding" _NL _NL);
else {
printf( "Battery information:" _NL
" hardware version ........: %02d" _NL
" software version ........: %02d" _NL,
hwVersion, getValue(BATTERY, BATTERY_REF_SW)
);
if (!gNoSerialNumbers)
printf( " part number .............: %05d" _NL
" item number .............: %05d" _NL,
((getValue(BATTERY, BATTERY_SN_PN_HI) << 8) + getValue(BATTERY, BATTERY_SN_PN_LO)),
((getValue(BATTERY, BATTERY_SN_ITEM_HI) << 8) + getValue(BATTERY, BATTERY_SN_ITEM_LO))
);
printf( " voltage .................: %0.2fV" _NL
" battery level ...........: %0.2f%%" _NL
" maximum voltage .........: %0.2f%%" _NL
" minimum voltage .........: %0.2f%%" _NL
" mean voltage ............: %0.2f%%" _NL
" resets ..................: %0d" _NL
" ggjrCalib ...............: %0d" _NL
" vctrlShorts .............: %0d" _NL
" lmd .....................: %0.2fAh" _NL
" cell capacity ...........: %0.2fAh" _NL _NL,
((getValue(BATTERY, BATTERY_STATUS_VBATT_HI) << 8) + getValue(BATTERY, BATTERY_STATUS_VBATT_LO)) * 0.001,
(getValue(BATTERY, BATTERY_STATUS_LEVEL) * 6.6667),
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMAX),
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMIN),
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMEAN),
(getValue(BATTERY, BATTERY_STATS_RESET_HI) << 8) + getValue(BATTERY, BATTERY_STATS_RESET_LO),
getValue(BATTERY, BATTERY_STSTS_GGJSRCALIB),
getValue(BATTERY, BATTERY_STSTS_VCTRLSHORTS),
((getValue(BATTERY, BATTERY_STATS_LMD_HI) << 8) + getValue(BATTERY, BATTERY_STATS_LMD_LO)) * 0.002142,
((getValue(BATTERY, BATTERY_CONFIG_CELLCAPACITY_HI) << 8) + getValue(BATTERY, BATTERY_CONFIG_CELLCAPACITY_LO)) * 0.001
);
printf( " charge time worst .......: %0d" _NL
" charge time mean ........: %0d" _NL
" charge cycles ...........: %0d" _NL
" full charge cycles ......: %0d" _NL
" power cycles ............: %0d" _NL
" battery temp max ........: %0d" _NL
" battery temp min ........: %0d" _NL _NL,
(getValue(BATTERY, BATTERY_STATS_CHARGETIMEWORST_HI) << 8) + getValue(BATTERY, BATTERY_STATS_CHARGETIMEWORST_LO),
(getValue(BATTERY, BATTERY_STATS_CHARGETIMEMEAN_HI) << 8) + getValue(BATTERY, BATTERY_STATS_CHARGETIMEMEAN_LO),
(getValue(BATTERY, BATTERY_STATS_BATTCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_BATTCYCLES_LO),
(getValue(BATTERY, BATTERY_STATS_BATTFULLCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_BATTFULLCYCLES_LO),
(getValue(BATTERY, BATTERY_STATS_POWERCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_POWERCYCLES_HI),
getValue(BATTERY, BATTERY_STATS_TBATTMAX),
getValue(BATTERY, BATTERY_STATS_TBATTMIN)
);
printChargeStats();
if (hwVersion >= 60)
printBatteryStats();
else
printf(" no battery details supported by battery hardware #%d" _NL _NL, hwVersion);
}
hwVersion = getValue(MOTOR, MOTOR_REF_HW);
if (hwVersion == 0)
printf("Motor not responding" _NL _NL);
else {
printf( "Motor information:" _NL
" hardware version ........: %02d" _NL
" software version ........: %02d" _NL
//" temperature .............: %02d" _DEGREE_SIGN "C"_NL
" speed limit .............: %02d Km/h" _NL,
hwVersion, getValue(MOTOR, MOTOR_REF_SW),
getValue(MOTOR, MOTOR_REALTIME_TEMP),
getValue(MOTOR, MOTOR_ASSIST_MAXSPEED)
);
wheelCirc = (getValue(MOTOR, MOTOR_GEOMETRY_CIRC_HI) << 8) + getValue(MOTOR, MOTOR_GEOMETRY_CIRC_LO);
printf( " wheel circumference .....: %d mm" _NL _NL, wheelCirc);
if (!gNoSerialNumbers)
printf( " part number .............: %05d" _NL
" item number .............: %05d" _NL _NL,
((getValue(MOTOR, MOTOR_SN_PN_HI) << 8) + getValue(MOTOR, MOTOR_SN_PN_LO)),
((getValue(MOTOR, MOTOR_SN_ITEM_HI) << 8) + getValue(MOTOR, MOTOR_SN_ITEM_LO))
);
}
}
int xmain(int argc, char **argv)
{
int err, doShutdown = 0, consoleInSlaveMode = 0;
struct TDeviceStatus status;
printf("BigXionFlasher USB " __BXF_VERSION__ _NL " (c) 2011-2013 by Thomas Koenig <info@bigxionflasher.org> - www.bigxionflasher.org" _NL);
if ((err=parseOptions(argc, argv) < 0))
exit(1);
if ((err = LoadDriver(TREIBER_NAME)) < 0) {
printf("LoadDriver error: %d" _NL, err);
goto error;
}
if ((err = CanInitDriver(NULL)) < 0) {
printf("CanInitDriver error: %d" _NL, err);
goto error;
}
if ((err = CanDeviceOpen(0, DEVICE_OPEN)) < 0) {
printf("CanDeviceOpen error: %d" _NL, err);
goto error;
}
CanSetSpeed(0, CAN_125K_BIT);
CanSetMode(0, OP_CAN_START, CAN_CMD_ALL_CLEAR);
CanGetDeviceStatus(0, &status);
if (status.DrvStatus >= DRV_STATUS_CAN_OPEN)
{
if (status.CanStatus == CAN_STATUS_BUS_OFF)
{
printf("CAN Status BusOff" _NL);
CanSetMode(0, OP_CAN_RESET, CAN_CMD_NONE);
}
}
else
{
printf("error: could not open device" _NL);
goto error;
}
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
if (consoleInSlaveMode)
{
printf("console already in salve mode. good!" _NL _NL);
}
else
{
if (gConsoleSetSlaveMode)
{
int retry = 20;
printf("putting console in salve mode ... ");
do {
setValue(CONSOLE, CONSOLE_STATUS_SLAVE, 1);
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
usleep(200000);
} while(retry-- && !consoleInSlaveMode);
doSleep(500); // give the console some time to settle
printf("%s" _NL _NL, consoleInSlaveMode ? "done" : "failed");
}
else
{
printf("console not in slave mode" _NL _NL);
}
}
if (gAssistInitLevel != -1)
{
printf("setting initial assistance level to %d" _NL, gAssistInitLevel);
setValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL, gAssistInitLevel);
}
if (gSetSpeedLimit > 0)
{
printf("set speed limit to %0.2f km/h" _NL, gSetSpeedLimit);
setSpeedLimit(gSetSpeedLimit);
doShutdown = 1;
} else if (gSetSpeedLimit == 0) {
printf("disable speed limit, drive carefully" _NL);
setSpeedLimit(0);
doShutdown = 1;
}
if (gSetMinSpeedLimit > 0) {
printf("set minimal speed limit to %0.2f km/h" _NL, gSetMinSpeedLimit);
setMinSpeedLimit(gSetMinSpeedLimit);
doShutdown = 1;
} else if (gSetMinSpeedLimit == 0) {
printf("disable minimal speed limit, drive carefully" _NL);
setMinSpeedLimit(0);
doShutdown = 1;
}
if (gSetThrottleSpeedLimit > 0) {
printf("set throttle speed limit to %0.2f km/h" _NL, gSetThrottleSpeedLimit);
setThrottleSpeedLimit(gSetThrottleSpeedLimit);
doShutdown = 1;
} else if (gSetThrottleSpeedLimit == 0) {
printf("disable throttle speed limit, drive carefully" _NL);
setThrottleSpeedLimit(0);
doShutdown = 1;
}
if (gSetMountainCap > 0) {
printf("set mountain cap level to %0.2f%%" _NL, ((int)gSetMountainCap / 1.5625) * 1.5625);
setValue(CONSOLE, CONSOLE_ASSIST_MOUNTAINCAP, gSetMountainCap / 1.5625);
}
if (gSetWheelCircumference > 0) {
printf("set wheel circumference to %d" _NL, gSetWheelCircumference);
setWheelCircumference(gSetWheelCircumference);
}
if (gPrintSystemSettings)
printSystemSettings();
if ((doShutdown && !gSkipShutdown) || gPowerOff) {
doSleep(1000);
printf("shutting down system." _NL);
setValue(BATTERY, BATTERY_CONFIG_SHUTDOWN, 1);
}
CanDownDriver();
UnloadDriver();
return 0;
error:
CanDownDriver();
UnloadDriver();
return 1;
}

View File

@@ -44,6 +44,7 @@
#include <QPainter>
#include "bcanimateddelegate.h"
#include "bcsliderstyle.h"
BCAnimatedDelegate::BCAnimatedDelegate(const BCValueList& valueList, QTableView* view)
@@ -52,41 +53,37 @@ BCAnimatedDelegate::BCAnimatedDelegate(const BCValueList& valueList, QTableView*
}
/*
QString BCAnimatedDelegate::displayText(const QVariant& dataValue, const QLocale& locale) const
{
// Wir prüfen, ob im Variant unser Struct steckt
if (dataValue.canConvert<const BCValue&>())
{
const BCValue& bc = dataValue.value<const BCValue/>();
//qDebug() << " --- YES: " << bc.label;
// Hier bauen wir den String zusammen, den man sieht,
// wenn KEIN Editor offen ist.
// Format: "Label: Wert Einheit"
return QString("%1: %2 %3").arg(bc.label, bc.formattedValue, "mmX");
}
else
{
//qDebug() << " --- Nö!";
}
// Fallback für normale Strings/Zahlen
return QStyledItemDelegate::displayText(dataValue, locale);
}
*/
QWidget *BCAnimatedDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const
{
/*
QVariant rawData = index.data(Qt::EditRole);
//if (!rawData.canConvert<BCValue*>())
if( index.column() == 1 )
return QStyledItemDelegate::createEditor(parent, option, index);
const BCValue& bc = *rawData.value<BCValue*>();
const BCValue& bcValue = *(_valueList[ index.row()].get());
Q_UNUSED(option)
Q_UNUSED(index)
auto* slider = new QSlider(Qt::Horizontal, parent);
slider->setRange(0, 100);
slider->setSingleStep(1);
slider->setPageStep(10);
//slider->setStyle(new FluentSliderStyle());
// Signal für sofortige Updates
connect(slider, &QSlider::valueChanged, this, [this, slider]()
{
// Commit data sofort bei Änderung
//emit const_cast<SliderDelegate*>(this)->commitData(slider);
});
return slider;
/*
// Nur bei Integern den Slider-Editor bauen
if (bc.value.typeId() == QMetaType::Int)
//if (bc.value.typeId() == QMetaType::Int)
{
QWidget *container = new QWidget(parent);
container->setAutoFillBackground(true);
@@ -96,8 +93,8 @@ QWidget *BCAnimatedDelegate::createEditor(QWidget *parent, const QStyleOptionVie
layout->setSpacing(10);
// Linkes Label (Name)
QLabel *lblName = new QLabel(bc.label, container);
lblName->setFixedWidth(80);
//QLabel *lblName = new QLabel(bcValue.label, container);
//lblName->setFixedWidth(80);
// Slider
QSlider *slider = new QSlider(Qt::Horizontal, container);
@@ -110,21 +107,22 @@ QWidget *BCAnimatedDelegate::createEditor(QWidget *parent, const QStyleOptionVie
lblUnit->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
lblUnit->setObjectName("lblUnit");
layout->addWidget(lblName);
//layout->addWidget(lblName);
layout->addWidget(slider);
layout->addWidget(lblUnit);
// Live-Update des Labels im Editor (aber noch kein Speichern im Model)
connect(slider, &QSlider::valueChanged, this, [=](int val){
connect(slider, &QSlider::valueChanged, this, [=](int val)
{
lblUnit->setText(QString("%1 %2").arg(val).arg("mm2"));
});
return container;
}
*/
return QStyledItemDelegate::createEditor(parent, option, index);
//return QStyledItemDelegate::createEditor(parent, option, index);
*/
}
void BCAnimatedDelegate::setEditorData(QWidget *editor, const QModelIndex& index) const
@@ -210,7 +208,7 @@ void BCAnimatedDelegate::paint(QPainter *painter, const QStyleOptionViewItem& op
if( row>-1 && row <= _valueList.size() )
{
const BCValue& bcValue = *(_valueList[ index.row()].get());
qDebug() << " --- paintSLider: " << bcValue.label << " type: " << (int)bcValue.valueType << " flags:" << bcValue.valueFlags.toInt() << " RO: " << bcValue.isReadOnly();
//qDebug() << " --- paintSLider: " << bcValue.label << " type: " << (int)bcValue.valueType << " flags:" << bcValue.valueFlags.toInt() << " RO: " << bcValue.isReadOnly();
if( !bcValue.isReadOnly())
paintSliderIndicator(painter,option,bcValue);
}
@@ -218,9 +216,9 @@ void BCAnimatedDelegate::paint(QPainter *painter, const QStyleOptionViewItem& op
default:
break;
}
}
void BCAnimatedDelegate::paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, int row) const
{
painter->save();
@@ -247,14 +245,15 @@ void BCAnimatedDelegate::paintHighlightRow(QPainter* painter, const QStyleOption
}
/**
* @brief Zeichnet eine passiven Slider, um den Wertebereich des übergebenen BCValue anzuzeigen.
* @param painter
* @param option
* @param bcValue
*/
void BCAnimatedDelegate::paintSliderIndicator(QPainter* painter, const QStyleOptionViewItem& option, const BCValue& bcValue) const
{
// wenn Werte readOnly sind, dann brauchen keinen EditHint
//if( bcValue.valueFlags.testFlag(BCValue::Flag::ReadOnly) )
// || bcValue.valueType == BCValue::ValueType::Plain )
// return;
// Hintergrund
if (option.state & QStyle::State_Selected)
{
@@ -267,6 +266,11 @@ void BCAnimatedDelegate::paintSliderIndicator(QPainter* painter, const QStyleOpt
}
// baby-Slider-Indikator zeichnen
// Anteil zwischen min und max berechnen
double ratio = bcValue.calcRatio();
if( !ratio)
return;
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
@@ -280,20 +284,27 @@ void BCAnimatedDelegate::paintSliderIndicator(QPainter* painter, const QStyleOpt
// Mini Progress Bar
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(0xE0E0E0));
QColor disabledText = option.palette.color(QPalette::Disabled, QPalette::Text);
painter->setBrush(disabledText);
painter->drawRoundedRect(barRect, 2, 2);
// Anteil zwischen min und max berechnen
double ratio = bcValue.calcRatio();
barRect.setWidth(barRect.width() * ratio );
painter->setBrush(QColor(0x0078D4));
//painter->setBrush(Qt::green);
//painter->setBrush( );
painter->drawRoundedRect(barRect, 2, 2);
painter->restore();
}
/**
* @brief Startet die Animation für die übergebene Zeile
* @param row
*/
void BCAnimatedDelegate::onHighlightRow(int row)
{
// Alte Animation für diese Zeile stoppen falls vorhanden
@@ -340,7 +351,11 @@ void BCAnimatedDelegate::onHighlightRow(int row)
anim->start(QAbstractAnimation::DeleteWhenStopped);
}
// Optional: alle Highlights sofort clearen
/**
* @brief Sopt alle gerade laufenden Animationen
*/
void BCAnimatedDelegate::clearAllHighlights()
{
for(auto* anim : std::as_const(_rowAnimations))
@@ -357,6 +372,12 @@ void BCAnimatedDelegate::clearAllHighlights()
}
}
/**
* @brief Zeichnet die übegebene Zeile neu.
* @param row
*/
void BCAnimatedDelegate::updateRow(int row)
{
if (_view && _view->model() && row >= 0)

View File

@@ -88,7 +88,6 @@ bool BCDeviceView::firstExpose()
*/
void BCDeviceView::onValueListReady( BCDevice::ID deviceID, BCValueList valueList )
{
//qDebug() << " --- onValueListReady: " << deviceID << ": " << valueList.size();
if(_devideID == deviceID)
_valueModel.takeValueList( valueList );
}

View File

@@ -87,7 +87,6 @@ TransmitResult BCDriverDummy::writeRawByte( uint32_t deviceID, uint8_t registerI
{
Q_UNUSED(deviceID)
Q_UNUSED(registerID)
//qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
return 0;
}

View File

@@ -180,8 +180,6 @@ BCDriver::DriverStateResult BCDriverTinyCan::setConsoleSlaveMode()
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
uint8_t slaveFlag = static_cast<uint8_t> (BC::ID::Cons_Status_Slave);
//qDebug() << "XXX BCDriverTinyCan::Driver Init: putting Console in slave mode ... ";
TransmitResult isSlave = 0;
// Already slave?
isSlave = readRawByte( console, slaveFlag );
@@ -341,7 +339,7 @@ retry:
if( err < 0 )
//throw BCException( "getValue error: could not receive value" );
//qDebug( "getValue error: could not receive value" );
qDebug( "getValue error: could not receive value" );
////qDebug() << "HÄÄ 2" <<msg.Id;
////qDebug() << "HÄÄ 2" <<msg.MsgLen;

View File

@@ -67,26 +67,22 @@ public:
: QProxyStyle()
{}
// Wichtig: Genug Platz für Handle reservieren
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override
{
switch (metric)
{
case PM_SliderThickness:
return 32; // Höhe für horizontalen Slider
return 24; // Höhe für horizontalen Slider
case PM_SliderLength:
return 20; // Handle-Größe
return 16; // Handle-Größe
case PM_SliderControlThickness:
return 20;
return 16;
case PM_SliderSpaceAvailable:
if (option)
{
if (const QStyleOptionSlider* sliderOpt = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
if (sliderOpt->orientation == Qt::Horizontal) {
if (const QStyleOptionSlider* sliderOpt = qstyleoption_cast<const QStyleOptionSlider*>(option))
{
return sliderOpt->rect.width() - 20;
} else {
return sliderOpt->rect.height() - 20;
}
}
}
return QProxyStyle::pixelMetric(metric, option, widget);
@@ -99,9 +95,10 @@ public:
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt,SubControl sc, const QWidget* widget) const override
{
if (cc == CC_Slider) {
if (const QStyleOptionSlider* slider = qstyleoption_cast<const QStyleOptionSlider*>(opt)) {
if (const QStyleOptionSlider* slider = qstyleoption_cast<const QStyleOptionSlider*>(opt))
{
QRect rect = slider->rect;
int handleSize = 20;
int handleSize = 16;
if (sc == SC_SliderHandle) {
// Handle Position korrekt berechnen
@@ -141,12 +138,10 @@ public:
QColor accentColor(0, 120, 212); // #0078D4
QColor inactiveColor(138, 136, 134); // #8A8886
QColor bgColor(255, 255, 255); // White background
if (slider->orientation == Qt::Horizontal) {
//QColor disabledText = option.palette.color(QPalette::Disabled, QPalette::Text);
//painter->setBrush(disabledText);
//QColor bgColor = Qt::green;//option->palette.color(QPalette::Base);
drawHorizontalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor);
} else {
drawVerticalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor);
}
return;
}
}
@@ -157,7 +152,8 @@ private:
void drawHorizontalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider,
const QColor& activeColor, const QColor& inactiveColor,
const QColor& bgColor) const {
const QColor& bgColor) const
{
QRect groove = slider->rect;
QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr);
@@ -178,16 +174,17 @@ private:
painter->drawRoundedRect(activeTrack, grooveHeight / 2, grooveHeight / 2);
// Handle (Thumb) - Fluent style is more subtle
int handleSize = 20;
int handleSize = 16;
QRect thumbRect(handle.center().x() - handleSize / 2,
handle.center().y() - handleSize / 2,
handleSize, handleSize);
// Hover effect - subtle glow
if (slider->state & State_MouseOver) {
if (slider->state & State_MouseOver)
{
painter->setBrush(QColor(activeColor.red(), activeColor.green(),
activeColor.blue(), 30));
int glowSize = 32;
int glowSize = 18;
QRect glow(handle.center().x() - glowSize / 2,
handle.center().y() - glowSize / 2,
glowSize, glowSize);
@@ -201,7 +198,7 @@ private:
// Inner circle for pressed state
if (slider->state & State_Sunken) {
int innerSize = 8;
int innerSize = 6;
QRect inner(handle.center().x() - innerSize / 2,
handle.center().y() - innerSize / 2,
innerSize, innerSize);
@@ -211,58 +208,6 @@ private:
}
}
void drawVerticalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider,
const QColor& activeColor, const QColor& inactiveColor,
const QColor& bgColor) const {
QRect groove = slider->rect;
QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr);
int grooveWidth = 4;
// Track sollte im Widget-Zentrum sein
int grooveX = slider->rect.center().x() - grooveWidth / 2;
// Full background track
QRect fullTrack(grooveX, groove.top(), grooveWidth, groove.height());
painter->setPen(Qt::NoPen);
painter->setBrush(inactiveColor.lighter(150));
painter->drawRoundedRect(fullTrack, grooveWidth / 2, grooveWidth / 2);
// Active track
int activeHeight = groove.bottom() - handle.center().y();
QRect activeTrack(grooveX, handle.center().y(), grooveWidth, activeHeight);
painter->setBrush(activeColor);
painter->drawRoundedRect(activeTrack, grooveWidth / 2, grooveWidth / 2);
// Handle
int handleSize = 20;
QRect thumbRect(handle.center().x() - handleSize / 2,
handle.center().y() - handleSize / 2,
handleSize, handleSize);
if (slider->state & State_MouseOver) {
painter->setBrush(QColor(activeColor.red(), activeColor.green(),
activeColor.blue(), 30));
int glowSize = 32;
QRect glow(handle.center().x() - glowSize / 2,
handle.center().y() - glowSize / 2,
glowSize, glowSize);
painter->drawEllipse(glow);
}
painter->setBrush(bgColor);
painter->setPen(QPen(activeColor, 2));
painter->drawEllipse(thumbRect);
if (slider->state & State_Sunken) {
int innerSize = 8;
QRect inner(handle.center().x() - innerSize / 2,
handle.center().y() - innerSize / 2,
innerSize, innerSize);
painter->setPen(Qt::NoPen);
painter->setBrush(activeColor);
painter->drawEllipse(inner);
}
}
};

View File

@@ -66,7 +66,6 @@ bool BCValue::isReadOnly() const
double BCValue::calcRatio() const
{
return 0.33;
double ratio = 0;

View File

@@ -45,8 +45,6 @@ BCValueModel::BCValueModel(QObject *parent)
}
/**
* @brief Gibt die interne Werteliste als const ref zurück
* @return Die WerteListe
@@ -164,34 +162,22 @@ QVariant BCValueModel::data(const QModelIndex& index, int role) const
return QVariant();
/*
Das Model Gibt hier, unabhängig von der DataRole, immer das
* gesamte BCValue Object zurück. Die Umsetzung von Status- und Typeinfromationen in GUI-Elemente
* findet nicht hier, sondern im BCDelagate statt.
// falsch! wie geben hier doch ordentlich die einzelwerte zurück
// Bonus: Rechtsbündig für Zahlen
if (role == Qt::TextAlignmentRole && (index.column() == 0 || index.column() == 2)) {
return Qt::AlignRight | Qt::AlignVCenter;
}
//return QVariant::fromValue( entry );
return QVariant();
*/
}
Qt::ItemFlags BCValueModel::flags(const QModelIndex& index) const
{
Qt::ItemFlags flag = Qt::NoItemFlags|Qt::ItemNeverHasChildren;
// die label spalte lässt sich nicht editieren
if (!index.isValid() || index.column() == 0 )
return Qt::NoItemFlags;
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
return flag;
int row = index.row();
if( row>-1 && row<_valueList.size() )
{
const BCValue& bcValue = *_valueList[row].get();
flag = bcValue.isReadOnly() ? flag : flag|Qt::ItemIsEditable|Qt::ItemIsEnabled;
}
return flag;
}