Files
BionxControl/bclegacy.cpp
2026-01-01 00:40:27 +01:00

829 lines
26 KiB
C++

/* 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
/*
class ThemeSwitchButton : public QPushButton {
Q_OBJECT
public:
explicit ThemeSwitchButton(QWidget *parent = nullptr)
: QPushButton(parent), m_isDarkMode(true)
{
// 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor
setFlat(true);
setCursor(Qt::PointingHandCursor);
setFixedSize(32, 24); // Kleiner Footprint im StatusBar
// CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt
// Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind
setStyleSheet(R"(
QPushButton {
border: none;
background-color: transparent;
font-size: 14pt;
}
QPushButton:hover {
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
border-radius: 4px;
}
)");
// 2. Initialer Status (Startet im Dark Mode -> zeigt Mond)
updateIcon();
// 3. Klick verbinden
connect(this, &QPushButton::clicked, this, &ThemeSwitchButton::toggle);
}
signals:
void themeChanged(bool isDark);
private slots:
void toggle() {
m_isDarkMode = !m_isDarkMode;
updateIcon();
emit themeChanged(m_isDarkMode);
}
private:
void updateIcon() {
// Logik:
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
// Hier: Zeige das Symbol des AKTUELLEN Modus.
setText(m_isDarkMode ? "🌙" : "☀️");
setToolTip(m_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode");
}
bool m_isDarkMode;
};
*/
/*
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr)
: QMainWindow(parent)
{
setWindowTitle("Fluent Theme Switcher");
resize(800, 600);
// --- STATUSBAR SETUP ---
QStatusBar *statBar = statusBar();
// Optional: Normale Nachricht links
statBar->showMessage("Ready");
// 1. Unseren Switcher erstellen
ThemeSwitchButton *themeBtn = new ThemeSwitchButton(this);
// 2. WICHTIG: Rechts hinzufügen
statBar->addPermanentWidget(themeBtn);
// 3. Signal verbinden: Button klick -> Theme ändern
connect(themeBtn, &ThemeSwitchButton::themeChanged, this, [this](bool isDark){
if (isDark) {
applyFluentDarkTheme(*qApp); // Funktion von vorhin
statusBar()->showMessage("Dark Mode Activated", 3000);
} else {
applyFluentLightTheme(*qApp); // Funktion von vorhin
statusBar()->showMessage("Light Mode Activated", 3000);
}
});
// Initiale Anwendung (Dark Mode)
applyFluentDarkTheme(*qApp);
}
};
*/
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;
}