DCLibraries/src/hwapi.cpp

4663 lines
129 KiB
C++

/*
* API to the PSA2020 Hardware
* All data come in from device controller via serial interface and will be stored
* PI is updated every 100ms
* This api uses stored data and returns them in the following functions
* created: Q1/2020 TS until Q2/21
14.7.23TS: patch for correct printer state in line 3364 in sys_getDeviceConditions(struct T_moduleCondition *devCond) const
8.9.2023 two new functions (end of file) for mifare test. Interface version 4.4 DC4.40...4.43
14.09.2023: Verriegelung eingebaut, nur noch gültige Abr.Daten zurückgeben, Suchbegriff: <epi_restoreVaultRecord>
alle Mifare-Funktionen ueberprueft und ggf verbessert
18.09.2023: Signal "Kasse entnommen" und Signale "Tuer auf/zu" ueberprueft
20.9.2023: in datif die Abfrage der DynMachineData massiv beschleunigt
und hier in hwapi die entprellten Werte fuer Tueren und Kasse verwenden.
Problem war: Signal "Kasse entnommen" war zu langsam -> manchmal abr nicht gesendet
*/
#include "hwapi.h"
#include "download_thread.h"
#include "reporting_thread.h"
#include <cstring>
#include <QThread>
#include <QDebug>
static uint32_t hwapi_lastStartAmount;
static uint32_t hwapi_lastTotalAmount;
static uint8_t hwapi_cash_lastCollectionState;
static uint8_t hwapi_paymentStarted;
static uint8_t hwapi_lastDoorState;
static uint8_t bl_startupStep;
hwapi::hwapi(QWidget *parent) : QObject(parent)
{
// constructor
qCritical() << " hwapi::hwapi() APP_VERSION:" << APP_VERSION;
qCritical() << " hwapi::hwapi() APP_BUILD_DATE:" << APP_BUILD_DATE;
qCritical() << " hwapi::hwapi() APP_BUILD_TIME:" << APP_BUILD_TIME;
qCritical() << " hwapi::hwapi() APP_EXTENDED_VERSION:" << APP_EXTENDED_VERSION;
qCritical() << "hwapi::hwapi() APP_EXTENDED_VERSION_LIB:" << APP_EXTENDED_VERSION_LIB;
// create or attach shared memory segment
m_sharedMem = SharedMem::getShm(sizeof(SharedMem));
if (m_sharedMem) {
if (m_sharedMem->isAttached()) {
qInfo() << "Shared memory ("
<< sizeof(SharedMem) << "bytes) created and attached";
}
} else {
qCritical() << "Creating/attaching shared memory failed";
}
//if (shdMem_firstUse()) // für Master raus
// {
#ifdef THIS_IS_CA_MASTER
#ifdef THIS_IS_CA_SLAVE
#error "SLAVE LIB COMPILED INTO MASTER"
#endif
myDatif = new T_datif(); // für die CAslave-Lib auskommentieren!
#endif
#ifdef THIS_IS_CA_SLAVE
#ifdef THIS_IS_CA_MASTER
#error "MASTER LIB COMPILED INTO MASTER"
#endif
#endif
// }
runProcess = new T_runProc();
sendWRcmd_INI();
hwapi_TimerPayment = new QTimer();
hwapi_TimerPayment->setSingleShot(true);
QTimer *hwapi_callPayProc = new QTimer();
connect(hwapi_callPayProc, SIGNAL(timeout()), this, SLOT(hwapi_slotPayProc()));
hwapi_callPayProc->setSingleShot(false);
hwapi_callPayProc->start(100); // in ms
// hwapi_triggerBL = new QTimer();
// connect(hwapi_triggerBL, SIGNAL(timeout()), this, SLOT(bl_performComplStart()));
// hwapi_triggerBL->setSingleShot(false);
// hwapi_triggerBL->stop();
hwapi_lastStartAmount=0;
hwapi_lastTotalAmount=0;
hwapi_cash_lastCollectionState=0;
hwapi_paymentStarted=0;
//csv_startCreatingFile(FILENAME_SHAREDDATA);
hwapi_lastDoorState=0; // default: all doors (should be) closed, coin box inserted
// bit0: upper door 1:middle 2:lower 3=cash-box out
bl_startupStep=0;
// connect(runProcess, SIGNAL(runProc_coinCollectionJustStarted()), this, SLOT(hwapi_coinCollectionJustStarted())); // geht nicht zuverlaessig!
connect(runProcess, SIGNAL(runProc_coinCollectionJustStarted()), this, SLOT(sub_slotCoin01()));
connect(runProcess, SIGNAL(runProc_coinCollectionAborted()), this, SLOT(sub_slotCoin02())); // hwapi_coinCollectionAborted()));
connect(runProcess, SIGNAL(runProc_gotNewCoin()), this, SLOT(sub_slotCoin03())); // hwapi_gotNewCoin()));
connect(runProcess, SIGNAL(runProc_payStopByMax()), this, SLOT(sub_slotCoin04())); // hwapi_payStopByMax()));
connect(runProcess, SIGNAL(runProc_payStopByPushbutton()), this, SLOT(sub_slotCoin05())); // hwapi_payStopByPushbutton()));
connect(runProcess, SIGNAL(runProc_payStopByEscrow()), this, SLOT(sub_slotCoin06())); // hwapi_payStopByEscrow()));
connect(runProcess, SIGNAL(runProc_payStopByError()), this, SLOT(sub_slotCoin07())); // hwapi_payStopByError()));
connect(runProcess, SIGNAL(runProc_payStopByTimeout()), this, SLOT(sub_slotCoin08())); // hwapi_payStopByTimeout()));
connect(runProcess, SIGNAL(runProc_payCancelled()), this, SLOT(sub_slotCoin09())); // hwapi_payCancelled()));
connect(runProcess, SIGNAL(runProc_coinProcessJustStopped()), this, SLOT(sub_slotCoin10())); // hwapi_coinProcessJustStopped()));
connect(runProcess, SIGNAL(runProc_doorServiceDoorOpened()), this, SLOT(sub_slotCoin11())); // hwapi_doorServiceDoorOpened()));
connect(runProcess, SIGNAL(runProc_doorVaultDoorOpened()), this, SLOT(sub_slotCoin12())); // hwapi_doorVaultDoorOpened()));
connect(runProcess, SIGNAL(runProc_doorCoinBoxRemoved()), this, SLOT(sub_slotCoin13())); // hwapi_doorCoinBoxRemoved()));
connect(runProcess, SIGNAL(runProc_doorCoinBoxInserted()), this, SLOT(sub_slotCoin14())); // hwapi_doorCoinBoxInserted()));
connect(runProcess, SIGNAL(runProc_doorCBinAndAllDoorsClosed()), this, SLOT(sub_slotCoin15())); // hwapi_doorCBinAndAllDoorsClosed()));
connect(runProcess, SIGNAL(runProc_doorAllDoorsClosed()), this, SLOT(sub_slotCoin16())); // hwapi_doorAllDoorsClosed()));
}
void hwapi::hwapi_slotPayProc(void)
{
}
void hwapi::sub_slotCoin01(void)
{
emit hwapi_coinCollectionJustStarted();
//qDebug()<<"hwapi::sub_slotCoin01()";
}
void hwapi::sub_slotCoin02(void)
{
emit hwapi_coinCollectionAborted();
//qDebug()<<"hwapi::sub_slotCoin02()";
}
void hwapi::sub_slotCoin03(void)
{
emit hwapi_gotNewCoin();
//qDebug()<<"hwapi::sub_slotCoin03()";
}
void hwapi::sub_slotCoin04(void)
{
emit hwapi_payStopByMax();
//qDebug()<<"hwapi::sub_slotCoin04()";
}
void hwapi::sub_slotCoin05(void)
{
emit hwapi_payStopByPushbutton();
//qDebug()<<"hwapi::sub_slotCoin05()";
}
void hwapi::sub_slotCoin06(void)
{
emit hwapi_payStopByEscrow();
qDebug()<<"hwapi::sub_slotCoin06()";
}
void hwapi::sub_slotCoin07(void)
{
emit hwapi_payStopByError();
//qDebug()<<"hwapi::sub_slotCoin07()";
}
void hwapi::sub_slotCoin08(void)
{
emit hwapi_payStopByTimeout();
//qDebug()<<"hwapi::sub_slotCoin08()";
}
void hwapi::sub_slotCoin09(void)
{
emit hwapi_payCancelled();
//qDebug()<<"hwapi::sub_slotCoin09()";
}
void hwapi::sub_slotCoin10(void)
{
emit hwapi_coinProcessJustStopped();
//qDebug()<<"hwapi::sub_slotCoin10()";
}
void hwapi::sub_slotCoin11(void)
{
emit hwapi_doorServiceDoorOpened();
}
void hwapi::sub_slotCoin12(void)
{
emit hwapi_doorVaultDoorOpened();
}
void hwapi::sub_slotCoin13(void)
{
emit hwapi_doorCoinBoxRemoved();
}
void hwapi::sub_slotCoin14(void)
{
emit hwapi_doorCoinBoxInserted();
}
void hwapi::sub_slotCoin15(void)
{
emit hwapi_doorCBinAndAllDoorsClosed();
}
void hwapi::sub_slotCoin16(void)
{
emit hwapi_doorAllDoorsClosed();
}
/*
void hwapi::sub_storeSendingText(QByteArray *buf) const
{
char local[70], copie[1350]; // 64byte more then max buffer size!
int LL, nn, len, maxruns=20;
epi_resetPrinterStack();
// make a copy of the incoming byteArray as the byteArray can not be moved (crash!)
tslib_strclr(copie, 0, 1350);
LL=buf->length();
for (nn=0; nn<LL; nn++)
{
copie[nn]=buf->at(nn);
}
tslib_strclr(local, 0, 66);
LL=buf->length();
if (LL>1280)
{
qDebug()<<"reducing text size from " << LL << " to 1280 bytes";
LL=1280; // Limit size
} else
qDebug()<<"\n printing text with " << LL << " bytes: ";
do
{
len=tslib_getMinimum(LL, 64);
tslib_strclr(local, 0, 66);
for (nn=0; nn<len; nn++)
{
local[nn]=copie[nn];
}
local[64]=0;
// delete already printed part of big buffer
if (LL<=64)
{
// last block
local[LL]=10;
// new line = cmd to printer: "print, even if line is not filled"
LL=0; // print complete
} else
{
LL-=64;
for (nn=0; nn<LL; nn++)
{
copie[nn]=copie[nn+64];
}
// pad remain with 0 (last but one block)
for (nn=LL; nn<64; nn++)
{
copie[nn]=0;
}
}
epi_storePrnText(local, uint8_t(len)); // no need to care for max PI size
// stores 64byte in PI with every call, maximal 20 calls (1280 byte)
} while(--maxruns>0 && LL>0);
}
*/
bool hwapi::dc_openSerial(int BaudNr, QString BaudStr, QString ComName, uint8_t connect) const
{
// BaudNr: 0:1200 1:9600 2:19200 3:38400 4:57600 5:115200
// BaudStr: for exapmle "19200"
// ComName: for example "COM48"
// connect: 0, 1
#ifdef THIS_IS_CA_MASTER
//qDebug() << "~~>LIB" << "dc_openSerial called... " ;
epi_setSerial(BaudNr, BaudStr, ComName, connect);
// Actions: open serial port with parameters
#else
BaudStr=ComName=""; BaudNr=0; connect=0; // to avoid compiler warning
qCritical()<<"hwapi: error CAslave cannot open serial";
return false;
return BaudNr; // to avoid compiler warning
return connect; // to avoid compiler warning
#endif
epi_setNowIsBootload(false);
return true;
}
void hwapi::dc_closeSerial(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_closeSerial();
#else
qCritical()<<"hwapi: error CAslave cannot close serial";
#endif
}
bool hwapi::dc_isPortOpen(void) const
{
return epi_isSerialPortOpen();
}
void hwapi::dc_autoRequest(bool on) const
{
// automatically request ALL digital and analog sensors, get time/date, get status information
epi_startEmmision(on);
}
void hwapi::dc_requTestResponse() const
{
//sendWRcmd_ setSendCommand0(SENDDIRCMD_TestSerial);
// CMD2DC_TestSerial
// replace by new command form:
sendFDcmd_set(0, CMD2DC_TestSerial, 0,0,0,0,0);
}
bool hwapi::dc_readAnswTestResponse() const
{
return epi_getResult_serialTestOK();
}
uint8_t hwapi::dc_isRequestDone(void) const
{
// retval: 0: request is still in progress
// 1: answer from DC2 was OK
// 2: wrong answer from DC2
return epi_getResultOfLastRequest();
}
uint16_t hwapi::dc_getCompletePayLoad(uint16_t plBufSiz, uint8_t *payLoad) const
{
// get data back in *pl, max 64 byte, can be used for diagnosis
// retval = nr of bytes received. If host buffer too small then
// only plBufSíz bytes are copied to pl
// plBufSíz=size of host buffer
return epi_getLastPayLoad( plBufSiz, payLoad);
}
void hwapi::dc_setWakeFrequency(uint8_t period) const
{
// RTC wakes DC2 (and PTU) by hardware signal every 32seconds
// change wake signal period to 1...64s
sendFDcmd_set(0, CMD2DC_setWakeFrequ,0, period,0,0,0);
}
void hwapi::dc_OrderToReset(void) const
{
uint8_t len, buf[160];
len=dcBL_restartDC(buf);
sendWRcmd_setSendBlock160(len, buf);
}
QString hwapi::dc_getSerialState(void) const
{
#ifdef THIS_IS_CA_MASTER
return epi_getTxt4comStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clrSerialStateText(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clrTxt4comStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
void hwapi::bl_sendDataDirectly(uint8_t length, uint8_t *buf) const
{
// send without protocol frame, needed for the DC bootloader
sendWRcmd_setSendBlock160(length, buf);
}
uint8_t hwapi::getRawRecLength(void) const
{
return epi_getRawRecLength();
}
uint8_t hwapi::getRawReceivedData(uint8_t *receivedData) const
{
return epi_getRawReceivedData(receivedData);
}
QString hwapi::dc_getSerialParams(void) const
{
return epi_getSlaveParamSTR();
}
QString hwapi::dc_getHWversion(void) const
{
return epi_loadHWver();
}
QString hwapi::dc_getSWversion(void) const
{
return epi_loadSWver();
}
QString hwapi::dc_getState(void) const
{
return epi_loadDCstate();
}
// ----------------------------------------------------------------------------------------------------------
// Date and Time
// ----------------------------------------------------------------------------------------------------------
uint8_t hwapi::rtc_getDateTime(struct Trtc_DateTime *rtc_DateTime) const
{
// void epi_getTime(uint8_t *hh, uint8_t *mm, uint8_t *ss);
// void epi_getDate(uint8_t *yy, uint8_t *mm, uint8_t *dd);
// void epi_getToday(uint8_t *dow, uint16_t *minOfToday, uint32_t *secOfToday);
uint8_t H, M, S;
uint16_t unused16;
uint32_t unused32;
epi_getTime(&H, &M, &S);
rtc_DateTime->rtc_hour=H;
rtc_DateTime->rtc_min=M;
rtc_DateTime->rtc_sec=S;
epi_getDate(&H, &M, &S);
rtc_DateTime->rtc_year=H;
rtc_DateTime->rtc_month=M;
rtc_DateTime->rtc_dayOfMonth=S;
epi_getToday(&H, &unused16, &unused32);
rtc_DateTime->rtc_dayOfWeek=H;
return 0;
}
uint8_t hwapi::rtc_setDateTime(void) const
{
//vorher nur: sendWRcmd_setSendCommand0(SENDDIRCMD_setTime);
// send PC time/date to slave
//uint8_t hour,min, sec, year, month, day, dayOfWeek,
//uint8_t dayOfYear, isLeap, weekOfYear;
uint8_t buff[15];
uint16_t uitmp;
QTime *systTime = new QTime();
// qDebug() << systTime->currentTime().hour() <<":"
// << systTime->currentTime().minute() <<":"
// << systTime->currentTime().second();
buff[0]=uint8_t(systTime->currentTime().hour());
buff[1]=uint8_t(systTime->currentTime().minute());
buff[2]=uint8_t(systTime->currentTime().second());
QDate *systDate = new QDate();
systDate->currentDate();
uitmp= uint16_t(systDate->currentDate().year());
buff[3]=uint8_t(uitmp);
buff[4]=uint8_t(uitmp>>8);
buff[5]=uint8_t(systDate->currentDate().month());
buff[6]=uint8_t(systDate->currentDate().day());
buff[7]=uint8_t(systDate->currentDate().dayOfWeek());
// uitmp=systDate->currentDate().dayOfYear();
// buff[8]=uint8_t(uitmp);
// buff[9]=uint8_t(uitmp>>8);
// buff[10]=uint8_t(systDate->currentDate().isLeapYear(systDate->currentDate().year()));
// buff[11]=uint8_t(systDate->currentDate().weekNumber()); //weekOfYear
// buff[12]=0;
longFDcmd_set(CMD2DC_sendTime,0,0,8,buff);
return 0;
}
void hwapi::rtc_getTime(uint8_t *hh, uint8_t *mm, uint8_t *ss) const
{
epi_getTime(hh, mm, ss);
}
void hwapi::rtc_getDate(uint8_t *yy, uint8_t *mm, uint8_t *dd) const
{
epi_getDate(yy, mm, dd);
}
uint8_t hwapi::rtc_getToday(uint8_t *dow, uint16_t *minOfToday, uint32_t *secOfToday) const
{
// dow=day of week, 1=monday...7
// minOfToday: 0=midnight...1439= 23:59
// secOfToday: 0=midnight...86399= 23:59:59
epi_getToday(dow, minOfToday, secOfToday);
return 0;
}
bool hwapi::rtc_isLeapYear(uint8_t *lastLeapYear, uint8_t *NextLeapYear) const
{
return epi_isLeapYear(lastLeapYear, NextLeapYear);
}
bool hwapi::rtc_isLeapYear(void) const
{
return epi_isLeapYear();
}
void hwapi::rtc_getWeek(uint8_t *DayOfWeek, uint8_t *HoursOfWeek, uint16_t *MinutesOfWeek) const
{
epi_getSpecialWeekTimeDate(DayOfWeek, HoursOfWeek, MinutesOfWeek);
}
void hwapi::rtc_getMonth(uint8_t *DayOfMonth, uint16_t *HoursOfMonth, uint16_t *MinutesOfMonth) const
{
epi_getSpecialMonthTimeDate(DayOfMonth, HoursOfMonth, MinutesOfMonth);
}
void hwapi::rtc_getYear(uint16_t *DayOfYear, uint16_t *HoursOfYear, uint32_t *MinutesOfYear) const
{
epi_getSpecialYearTimeDate(DayOfYear, HoursOfYear, MinutesOfYear);
}
QString hwapi::rtc_getTimStr() const
{
uint8_t hh, mm, ss, buf[20], nn;
QString qbuf;
char ctmp;
qbuf.clear();
for (nn=0; nn<20; nn++) buf[nn]=0;
epi_getTime(&hh, &mm, &ss);
GetTimeString(hh, mm, ss, HourSys24h, MITSEK, buf); // about 12byte long
for (nn=0; nn<20; nn++)
{
ctmp=buf[nn];
qbuf[nn]=ctmp;
}
return qbuf;
}
QString hwapi::rtc_getDatStr() const
{
uint8_t day, month, year, buf[20], nn;
QString qbuf;
char ctmp;
qbuf.clear();
for (nn=0; nn<20; nn++) buf[nn]=0;
epi_getDate(&year, &month, &day);
GetDateString(day, month, 0x20, year, DateFormatDeutsch, 0, buf);
for (nn=0; nn<20; nn++)
{
ctmp= buf[nn];
qbuf[nn]=ctmp;
}
return qbuf;
}
QString hwapi::rtc_getTimDatStr() const
{
// style: 0: hh:mm 1: hh:mm:ss
QString qbuf;
qbuf.clear();
qbuf.append(rtc_getTimStr());
qbuf.append(" ");
qbuf.append(rtc_getDatStr());
return qbuf;
}
// UID
void hwapi::dc_getUID8byte(uint8_t *buf8byteUid) const
{
epi_getUIDdec(buf8byteUid);
}
QString hwapi::dc_getUIDstr() const
{
return epi_getUIDstr();
}
uint64_t hwapi::dc_getUIDnumber(void) const
{
uint64_t retval=0;
uint8_t buf8byteUid[12], nn;
epi_getUIDdec(buf8byteUid);
for (nn=8; nn>0; nn--)
{
retval+=buf8byteUid[nn-1];
retval<<=8; // *256
}
return retval;
}
// ----------------------------------------------------------------------------------------------------------
// analogs
// ----------------------------------------------------------------------------------------------------------
uint32_t hwapi::dc_getTemperature(void) const
{
//
return epi_loadMeasureValue(MEASCHAN_TEMPERATURE);
}
QString hwapi::dc_getTemperaturStr(void) const
{
return epi_getSlaveTemperatureStr();
}
uint32_t hwapi::dc_getVoltage(void) const
{
// in mV, e.g. 12300 = 12,3V
return epi_loadMeasureValue(MEASCHAN_VOLTAGE);
}
QString hwapi::dc_getVoltagStr(void) const
{
return epi_getSlaveVoltageStr();
}
bool hwapi::dc_mainFuseIsOk(void) const
{
uint32_t ulong=epi_loadMeasureValue(MEASCHAN_VOLTAGE); // in mV, e.g. 12300 = 12,3V
if (ulong>3000)
return true;
return false;
}
// ------------------------------------------------------------------------------
// digital outputs
// ------------------------------------------------------------------------------
// Locks:
uint8_t hwapi::lock_switchUpperLock(uint8_t dir) const
{
// dir 0=off 1=up 2=down
sendFDcmd_set(CMD2DC_MOV_UPLOCK,0,0, dir,0,0,0);
return 0;
}
uint8_t hwapi::lock_switchLowerLock(uint8_t dir) const
{
// dir 0=off 1=up 2=down
sendFDcmd_set(CMD2DC_MOV_DNLOCK,0,0, dir,0,0,0);
return 0;
}
void hwapi::lock_switchVaultDoor(void) const
{
sendFDcmd_set(CMD2DC_VAULT_DOOR,0,0, 0,0,0,0);
}
void hwapi::coin_switchRejectMotor(uint8_t dir) const
{
sendFDcmd_set(CMD2DC_REJMOT_ON,0,0, dir,0,0,0);
}
void hwapi::coin_rejectCoins(void) const
{
sendFDcmd_set(CMD2DC_REJMOT_RUN,0,0, 0,0,0,0);
}
void hwapi::led_switchLedService(uint8_t on) const
{
sendFDcmd_set(CMD2DC_LED_IN, CMD2DC_RdBkAllOutputs, 0, on, 0, 0, 0);
}
void hwapi::led_switchLedPaper(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendFDcmd_set(CMD2DC_LED_TICKET, CMD2DC_RdBkAllOutputs,0, on, ton, tof, 0);
}
void hwapi::led_switchLedPinPad(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendFDcmd_set(CMD2DC_LED_PIN, CMD2DC_RdBkAllOutputs, 0, on, ton, tof, 0);
}
void hwapi::led_switchLedStart(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendFDcmd_set(CMD2DC_LED_START, CMD2DC_RdBkAllOutputs,0, on, ton, tof, 0);
}
void hwapi::led_switchLedCoinbassin(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendFDcmd_set(CMD2DC_LED_COIN, CMD2DC_RdBkAllOutputs, 0, on, ton, tof, 0);
}
void hwapi::fan_switchFan(bool on) const
{
sendFDcmd_set(CMD2DC_FAN, CMD2DC_RdBkAllOutputs,0, on, 0, 0, 0);
}
void hwapi::alarm_switchSiren(bool on) const
{
sendFDcmd_set(CMD2DC_SIREN, CMD2DC_RdBkAllOutputs,0, on, 0, 0, 0);
}
void hwapi::bar_OpenBarrier(bool open) const
{
sendFDcmd_set(CMD2DC_BARRIER, CMD2DC_RdBkAllOutputs,0, open, 0, 0, 0);
}
void hwapi::ptu_switchWake(bool WAKEACTIVE) const
{
sendFDcmd_set(CMD2DC_WAKEPTU,0,0, WAKEACTIVE,0,0,0);
}
// AUX-IO's or barcode reader
void hwapi::aux_power(bool on) const
{
sendFDcmd_set(CMD2DC_SWITCHAUXPWR, CMD2DC_RdBkAllOutputs, 0, on,0,0,0);
}
void hwapi::aux_setUsage(uint8_t PinDirection) const
{
// bit 0= Aux1 bit5=Aux6 1=output 0=input with pullup
sendFDcmd_set(CMD2DC_SWITCHAUXDDR, CMD2DC_RdBkAllOutputs,0, PinDirection,0,0,0);
}
void hwapi::aux_setOutputs(uint8_t PinIsHigh) const
{
// PinIsHigh bit 0..5 =Aux1...6 1=output high 0=set output low
sendFDcmd_set(CMD2DC_SWITCHAUXOUT, CMD2DC_RdBkAllOutputs,0, PinIsHigh,0,0,0);
}
void hwapi::lock_switchContactPower(bool on) const
{
sendFDcmd_set(CMD2DC_UCONTACTON, 0,0, on, 0,0,0);
}
void hwapi::prn_switchPower(bool on) const
{
// also switches and enables serial driver
//sendWRcmd_ setSendCommand4(SENDDIRCMD_PRN2_SWONOFF, on,0,0,0);
indat_storePrinterPower(on);
// PRINTER-ON/OFF zusätzlich statisch abspeichern
// Status-request soll nur gesendet werden wenn der Drucker ein ist
// Status-Abfrage (hier in HWapi) gibt 0 zurück wenn power-off
// dito mit allen anderen Geräten!
// pi ---> storeINdata.cpp speichert diese statische Info (printer on/off) UND
// auch alles rückgelesene
sendFDcmd_set(CMD2DC_PRINTERON,0,0, on,0,0,0);
}
void hwapi::mif_readerOn(bool on) const
{
// DC2 also switches and enables serial driver
//sendWRcmd_ setSendCommand4(SENDDIRCMD_MIF_SWONOFF, on,0,0,0);
sendFDcmd_set(CMD2DC_MIFREADERON,0,0, on,0,0,0);
indat_storeMifarePower(on);
if (on==false)
{
gpi_clearMifAtbData(); // neu 14.9.23
gpi_clearMifHwData(); // neu 8.9.23
}
}
void hwapi::mif_creatAtbCard(uint8_t cardType) const
{
sendFDcmd_set(CMD2DC_MIFREADERON,0,0, cardType,0,0,0);
indat_storeMifarePower(cardType);
}
void hwapi::mod_switchPower(bool on) const
{
sendFDcmd_set(CMD2DC_MOD_ON,0,0, on,0,0,0);
}
void hwapi::mod_switchWake(bool WAKEACTIVE) const
{
sendFDcmd_set(CMD2DC_MOD_WAK,0,0, WAKEACTIVE,0,0,0);
}
void hwapi::mdb_switchPower(bool on) const
{
sendFDcmd_set(CMD2DC_MDB_ON,0,0, on,0,0,0);
indat_storeMDBisOn(CMD2DC_MDB_ON);
}
void hwapi::mdb_switchWake(bool WAKEACTIVE) const
{
sendFDcmd_set(CMD2DC_MDB_SETWAK,0,0, WAKEACTIVE,0,0,0);
}
void hwapi::credit_switchPower(bool on) const
{
sendFDcmd_set(CMD2DC_CRED_ON,0,0, on,0,0,0);
}
void hwapi::credit_switchWake(bool WAKEACTIVE) const
{
sendFDcmd_set(CMD2DC_CRED_WAK,0,0, WAKEACTIVE,0,0,0);
}
void hwapi::shut_move(bool open) const
{
// true:open false:close
sendFDcmd_set(CMD2DC_SHUTTER_OPEN, 0,0, open, 0,0,0);
}
void hwapi::esc_moveFlaps(uint8_t flap ) const
{
// 0: close both 1: open take-flap 2: open return
sendFDcmd_set(CMD2DC_ESCR_OPEN,0,0, flap, 0,0,0);
}
// ------------------------------------------------------------------------------
// door, cashbox and lock switches
// ------------------------------------------------------------------------------
uint8_t hwapi::door_getSwitches(void) const
{
// retval // bit0: upper door 1: low door 2:vault door
uint8_t ret;
ret= epi_getDI_doorSwitches();
// bit0: upper door 1: low door 2:vault door
ret &= 0x08;
return ret;
}
bool hwapi::door_isUpperDoorOpen(void) const
{
// uint8_t ret;
// ret= epi_getDI_doorSwitches();
// // bit0: upper door 1: low door 2:vault door
// if (ret & 1)
// return true;
// return false;
// new, since 20.9.23: use debounced values:
struct T_dynamicCondition myDynMachCond;
sys_getDynMachineConditions(&myDynMachCond);
if (myDynMachCond.upperDoor==0) // 0=zu
return false;
return true; // report "open" even if undefined because "closed" is more important
}
bool hwapi::door_isLowerDoorOpen(void) const
{
// uint8_t ret;
// ret= epi_getDI_doorSwitches();
// if (ret & 2)
// return false;
// return true;
// new, since 20.9.23: use debounced values:
struct T_dynamicCondition myDynMachCond;
sys_getDynMachineConditions(&myDynMachCond);
if (myDynMachCond.lowerDoor==0) // 0=zu
return false;
return true; // report "open" even if undefined because "closed" is more important
}
bool hwapi::vault_isVaultDoorOpen(void) const
{
// uint8_t ret;
// ret= epi_getDI_doorSwitches();
// // bit0: upper door 1: low door 2:vault door
// if (ret & 4)
// return true;
// return false;
// new, since 20.9.23: use debounced values:
struct T_dynamicCondition myDynMachCond;
sys_getDynMachineConditions(&myDynMachCond);
if (myDynMachCond.middleDoor==0) // 0=zu
return false;
return true; // report "open" even if undefined because "closed" is more important
}
uint8_t hwapi::vault_getSwitches(void) const
{
// retval bit0: cash box, bit 1: bill box
uint8_t ret;
ret=epi_getDI_vaultSwitches(); // bit0: cash box 1: bill box in
ret&=0x03;
return ret;
}
bool hwapi::vault_isCoinVaultIn(void) const
{
// uint8_t ret;
// ret=epi_getDI_vaultSwitches(); // bit0: cash box 1: bill box in
// if (ret & 1)
// return true;
// return false;
// new, since 20.9.23: use debounced values:
struct T_dynamicCondition myDynMachCond;
sys_getDynMachineConditions(&myDynMachCond);
if (myDynMachCond.CBinDebounced==0) // 0:fehlt 1:drin
return false;
return true;
}
bool hwapi::vault_isBillVaultIn(void) const
{
uint8_t ret;
ret=epi_getDI_vaultSwitches(); // bit0: cash box 1: bill box in
if (ret & 2)
return true;
return false;
}
uint8_t hwapi::door_getLocks(void) const
{
// retval bit0: upper lever is up
// bit1: upper lever is down
// bit2: lower lever is up
// bit3: lower lever is down
uint8_t ret;
ret= epi_getDI_lockSwitches();
// retval: bit 0: upper lockbar up bit1: upper lockbar is down
// bit 2: lower lockbar up bit1: lower lockbar is down
ret&=0x0F;
return ret;
}
bool hwapi::door_upperDoorIsLocked(void) const
{
uint8_t ret;
ret= epi_getDI_lockSwitches();
if (ret & 2)
return true;
return false;
}
bool hwapi::door_upperDoorIsUnlocked(void) const
{
uint8_t ret;
ret= epi_getDI_lockSwitches();
if (ret & 1)
return true;
return false;
}
bool hwapi::door_lowerDoorIsLocked(void) const
{
uint8_t ret;
ret= epi_getDI_lockSwitches();
if (ret & 8)
return true;
return false;
}
bool hwapi::door_lowerDoorIsUnlocked(void) const
{
uint8_t ret;
ret= epi_getDI_lockSwitches();
if (ret & 4)
return true;
return false;
}
bool hwapi::bar_optoIn1isOn(void) const
{
uint8_t ret=epi_getDI_optos();
// bit0: opto in 1 1: opto in 2
if (ret & 1)
return true;
return false;
}
bool hwapi::bar_optoIn2isOn(void) const
{
uint8_t ret=epi_getDI_optos();
// bit0: opto in 1 1: opto in 2
if (ret & 2)
return true;
return false;
}
uint8_t hwapi::aux_getAuxInputs(void) const
{
// retval: bit0=Aux1....Bit5=Aux6
// 0: input low 1:input high
uint8_t ret=epi_getDI_auxIn();
// bit0: auxin 1 ... 5: auxin 6
ret &=0x3F;
return ret;
}
bool hwapi::ptu_WakeINisActive(void) const
{
return epi_getDI_ptuWake();
}
bool hwapi::mdb_WakeINisActive(void) const
{
return epi_getDI_mdbWake();
}
bool hwapi::prn_readyINisActive(void) const
{
return epi_getDI_prnReady();
}
bool hwapi::coid_isAttached(void) const
{
return epi_getDI_CoinAttach();
}
bool hwapi::coin_escrowIsOpen(void) const
{
return epi_getDI_CoinEscrow();
}
bool hwapi::mif_cardIsAttached(void) const
{
return epi_getDI_mifareCardTapped();
}
//bool hwapi::mod_WakeINisActive(void)
//{
// return epi_getDI_modemWake();
//}
bool hwapi::door_isContactPowerOn(void) const
{
return epi_getDI_contactPwr();
}
bool hwapi::mif_isMifarePowerOn(void) const
{
bool mo=indat_isMifareOn();
bool mi=epi_getDI_mifarePwr();
if (mo && mi)
return true;
return false;
}
bool hwapi::mdb_testIsmdbTxDon(void) const
{
return epi_getDI_mdbTxd();
//return mdb_busVoltageOk(); gleich?
}
bool hwapi::aux_isAuxPowerOn(void) const
{
return epi_getDI_auxPwr();
}
bool hwapi::mod_isGsmPowerOn(void) const
{
return epi_getDI_gsmPwr();
}
bool hwapi::cred_isCreditPowerOn(void) const
{
return epi_getDI_creditPwr();
}
bool hwapi::prn_isPrinterPowerOn(void) const
{
return epi_getDI_printerPwr();
}
uint8_t hwapi::prn_PrnFuseIsOk(void) const
{
//retval: 0: fuse blown 1: fuse OK 2:unknown as printer power is off
if (!epi_getDO_printerPwr())
return 2; // unknown as printer power is off
if (epi_getDI_printerPwr())
return 1; // printer voltage is OK
return 0; // fuse blown
}
bool hwapi::mdb_isMdbPowerOn(void) const
{
//return epi_getDI_mdbPwr(); // all DIs byte 4 bit 7 da ist was verschoben
return mdb_deviceVoltageOK(); // gleich? aus MDB_GET_STATE=107 Byte[1]
}
bool hwapi::cash_getRejectMotorHomePos(void) const
{
// DI=low in Homepos
if (epi_getDI_rejectMotor_homepos())
return 0;
return 1;
}
uint8_t hwapi::cash_getLowPaperSensor(void) const
{
// 0: Sensor sees paper 1: no paper 99: off
return epi_getDI_npe_sensor();
}
// ------------------------------------------------------------------------------
// request commands
// ------------------------------------------------------------------------------
// all read-requests can be sent manually by the following functions
// or automatically in background by: void hwapi::dc_autoRequest(bool on)
void hwapi::request_DC2serialConfig() const
{
sendFDcmd_set(0,CMD2DC_GetSerialConfig,0,0,0,0,0);
}
void hwapi::request_DC2_HWversion() const
{
sendFDcmd_set(0,CMD2DC_RdBkHWversion,0,0,0,0,0);
}
void hwapi::request_DC2_SWversion() const
{
sendFDcmd_set(0,CMD2DC_RdBkSWversion,0,0,0,0,0);
}
void hwapi::request_DC2_condition() const
{
sendFDcmd_set(0,CMD2DC_RdBkDCstate,0,0,0,0,0);
}
void hwapi::request_DC2_UID() const
{
sendFDcmd_set(0,CMD2DC_RdBkUID,0,0,0,0,0);
}
void hwapi::request_DC2_TimeAndDate() const
{
sendFDcmd_set(0,CMD2DC_RdBkTime,0,0,0,0,0);
}
void hwapi::request_DC2_analogues() const
{
sendFDcmd_set(0,CMD2DC_RdBkAnalog,0,0,0,0,0);
}
void hwapi::request_DC2_digitalInputs() const
{
sendFDcmd_set(0,CMD2DC_GetAllInputs,0,0,0,0,0);
}
void hwapi::request_DC2_digitalOutputs() const
{
sendFDcmd_set(0,CMD2DC_RdBkAllOutputs,0,0,0,0,0);
}
// ------------------------------------------------------------------------------
// the folowing device state requests are deployed only if device is powered up:
void hwapi::request_PrinterHwState() const
{
sendFDcmd_set(0,CMD2DC_RdBk_PrnState,0,0,0,0,0);
}
void hwapi::request_PrinterCurrentFonts() const
{
sendFDcmd_set(0,CMD2DC_RdBk_PrnFonts,0,0,0,0,0);
}
void hwapi::request_PrinterStateComplete() const
{
sendFDcmd_set(0,CMD2DC_RdBk_AllPrnData,0,0,0,0,0);
}
void hwapi::request_MifareReaderState() const
{
sendFDcmd_set(0, 24, 0, 0,0,0,0); // return reader type, card state and type and card UID
}
void hwapi::request_MifareCardType() const
{
sendFDcmd_set(0, 109, 0, 0,0,0,0); // ATB Card Type: upper/lower door, test card and card holder
}
void hwapi::request_MifareAtbType() const
{
sendFDcmd_set(0,25,0,0,0,0,0);
}
void hwapi::request_MifareID() const
{
this->request_MifareReaderState();
}
void hwapi::request_MifareData(uint8_t dataBlockNumber) const
{
if (dataBlockNumber<12) // 1k cards return 12 data blocks, 4k cards would return 54 data blocks (not implemented)
sendFDcmd_set(0,28,0, dataBlockNumber,0,0,0); // 1st data = card sequence =blk nr (0...15)
}
void hwapi::request_MDB_Status() const
{
sendFDcmd_set(0,CMD2DC_MDB_GET_STATE,0,0,0,0,0);
}
//void hwapi::request_MDB_wakeInLine() const
//{
// sendWRcmd_setSendCommand0(SEND_REQU_MDB_GETWAK);
//}
void hwapi::request_MDB_lastResponse() const
{
sendFDcmd_set(0,CMD2DC_MDB_GETRESP,0,0,0,0,0);
}
void hwapi::request_EMP_allParameters() const
{
sendFDcmd_set(0,CMD2DC_EMP_GET_ALL,0,0,0,0,0);
}
void hwapi::request_EMP_lastCoin() const
{
sendFDcmd_set(0,CMD2DC_EMP_GOTCOIN,0,0,0,0,0);
}
// ------------------------------------------------------------------------------
// readback digital outputs of connected devices
// these functions are not needed for normal operation
// but can be used to test and verify conditions
// ------------------------------------------------------------------------------
bool hwapi::test_getDO_mdbRXtst(void) const
{
return epi_getDO_mdbRxTestOut();
}
uint8_t hwapi::lock_getDO_motors(void) const
{
// bit0: upper lock forward bit 1 backward
// bit2: lower lock forward bit 3 backward
return epi_getDO_motorOuts();
}
uint8_t hwapi::test_serialState(void) const
{
// test on-board signals for the serials
// serial drv on/off, Serial mux1, Serial mux2
uint8_t ret=epi_getDO_serialSwitch();
// serial drv on/off, Serial mux1, Serial mux2
ret &=0x07;
return ret;
}
bool hwapi::test_serialIsOn(void) const
{
return epi_getDO_serialDriverIsOn();
}
bool hwapi::test_serialMux1isSetToPrinter(void) const
{
return epi_getDO_serialMux1isSetToPrinter();
// mux1 off: serial is switched to printer
}
bool hwapi::test_serialMux1isSetToModem(void) const
{
return epi_getDO_serialMux1isSetToModem();
// mux1 on: serial is switched to modem
}
bool hwapi::test_serialMux2isSetToCredit(void) const
{
return epi_getDO_serialMux2isSetToCredit();
// mux2 off: serial is switched to credit card terminal
}
bool hwapi::test_serialMux2isSetToMifare(void) const
{
return epi_getDO_serialMux2isSetToMifare();
// mux2 on: serial is switched to mifare reader
}
bool hwapi::led_coinIsOn(void) const
{
return epi_getDO_led_coin();
}
bool hwapi::led_frontIsOn(void) const
{
return epi_getDO_led_front();
}
bool hwapi::led_ticketIsOn(void) const
{
return epi_getDO_led_ticket();
}
bool hwapi::led_pinIsOn(void) const
{
return epi_getDO_led_pin();
}
bool hwapi::led_StartIsOn(void) const
{
return epi_getDO_led_start();
}
bool hwapi::led_insideIsOn(void) const
{
return epi_getDO_led_inside();
}
bool hwapi::fan_isOn(void) const
{
return epi_getDO_fan();
}
bool hwapi::siren_isOn(void) const
{
return epi_getDO_sirene();
}
bool hwapi::bar_relayIsOn(void) const
{
return epi_getDO_relay();
}
bool hwapi::ptu_WakeOutIsOn(void) const
{
return epi_getDO_ptuWake();
}
bool hwapi::aux_powerIsOn(void) const
{
return epi_getDO_auxPower();
}
bool hwapi::coin_shutterIsOpen(void) const
{
return epi_getDO_coinShutterOpen();
}
bool hwapi::coin_shutterTestOutput(void) const
{
return epi_getDO_coinShutterTest();
}
uint8_t hwapi::coin_escrowFlapOpened(void) const
{
// retval: 1:return flap is open 2:take flap is open 0:closed
return epi_getDO_coinEscrow();
}
// ------------------------------------------------------------------------------
// devices are operated by DC
// processes with more then one devices
// timer controlled or long term processes
// ------------------------------------------------------------------------------
void hwapi::sendDeviceSettings(uint8_t kindOfPrinter, uint8_t kindOfCoinChecker,
uint8_t kindOfMifareReader, uint8_t suppressSleep,
uint8_t kindOfModem, uint8_t kindOfCredit) const
{
uint8_t buf[64];
tslib_strclr(buf,0,64);
buf[0]=kindOfPrinter;
buf[1]=kindOfCoinChecker;
buf[2]=kindOfMifareReader;
buf[3]=suppressSleep;
buf[4]=kindOfModem;
buf[5]=kindOfCredit;
longFDcmd_set(CMD2DC_DEVICE_PARAM, 0, 0, 6, buf);
}
void hwapi::request_ReadbackDeviceSettings() const
{
sendFDcmd_set(0,CMD2DC_RDBK_DEV_PARA,0,0,0,0,0);
}
void hwapi::readback_DeviceSettings(uint8_t *length, uint8_t *data) const
{
epi_restoreRbDeviceSettings(length, data);
/*
buf66[0]=devPara.kindOfPrinter;
buf66[1]=devPara.kindOfCoinChecker;
buf66[2]=devPara.kindOfMifareReader;
buf66[3]=devPara.suppressSleepMode;
buf66[4]=devPara.kindOfModem;
buf66[5]=devPara.kindOfCreditcard;
buf66[6]=devPara.CoinEscrow;
buf66[7]=devPara.CoinRejectUnit;
buf66[8]=devPara.CoinShutter;
buf66[9]=devPara.BillAcceptor;
buf66[10]=devPara.usevaultLock;
buf66[11]=devPara.autoAlarm;
buf66[12]=devPara.autoOpen;
buf66[13]=devPara.printAccReceipt;
buf66[14]=devPara.printDoorReceipt;
buf66[15]=devPara.printTokenTicket;
uitmp=devPara.VaultFullWarnLevel;
buf66[16]=swl_getOneByteFromUint(uitmp, GETLOWBYT);
buf66[17]=swl_getOneByteFromUint(uitmp, GETHIGHBYT);
uitmp=devPara.VaultFullErrorLevel;
buf66[18]=swl_getOneByteFromUint(uitmp, GETLOWBYT);
buf66[19]=swl_getOneByteFromUint(uitmp, GETHIGHBYT);
*/
}
// ....................................................................................
void hwapi::sendMachineID(uint16_t customerNr, uint16_t machineNr,
uint16_t borough, uint16_t zone,
uint16_t alias, char *location) const
{
uint8_t buf[64];
tslib_strclr(buf,0,64);
buf[0]=uint2uchar(customerNr, LOWBYTE);
buf[1]=uint2uchar(customerNr, HIGHBYTE);
buf[2]=uint2uchar(machineNr, LOWBYTE);
buf[3]=uint2uchar(machineNr, HIGHBYTE);
buf[4]=uint2uchar(borough, LOWBYTE);
buf[5]=uint2uchar(borough, HIGHBYTE);
buf[6]=uint2uchar(zone, LOWBYTE);
buf[7]=uint2uchar(zone, HIGHBYTE);
buf[8]=uint2uchar(alias, LOWBYTE);
buf[9]=uint2uchar(alias, HIGHBYTE);
tslib_strcpy(location, &buf[10], 32);
longFDcmd_set(CMD2DC_SEND_MACH_ID,0,0,42,buf);
}
void hwapi::request_ReadbackMachineID() const
{
sendFDcmd_set(0,CMD2DC_RDBK_MACH_ID,0,0,0,0,0);
}
void hwapi::readback_machineIDdata(uint8_t *length, uint8_t *data) const
{
epi_restoreMachineIDsettings(length, data);
}
// ....................................................................................
static uint16_t hwapi_shutterTime;
// locks, 2.Level: (Motor stops automatical on end switch or by 5s timeout)
uint8_t hwapi::lock_openUpperDoor(void) const
{
// paras: dat2: 1=upper door lock 2=lower
// dat1: 1=open 2=close
sendFDcmd_set(CMD2DC_UPPER_DOOR,0,0,1,0,0,0);
return 0;
}
uint8_t hwapi::lock_closeUpperDoor(void) const
{
sendFDcmd_set(CMD2DC_UPPER_DOOR,0,0,2,0,0,0);
return 0;
}
uint8_t hwapi::lock_openLowerDoor(void) const
{
sendFDcmd_set(CMD2DC_LOWER_DOOR,0,0,1,0,0,0);
return 0;
}
uint8_t hwapi::lock_closeLowerDoor(void) const
{
sendFDcmd_set(CMD2DC_LOWER_DOOR,0,0,2,0,0,0);
return 0;
}
void hwapi::shut_openOnce(void) const
{
// and close automatic after shutter time
uint16_t zeit=hwapi_shutterTime;
zeit/=100;
sendFDcmd_set(CMD2DC_SHUTTER_OPEN3S, 0,0,uint8_t(zeit) ,0,0,0);
}
void hwapi::shut_openForCoin(bool start) const
{
// start=true: start opening flap if coin is attached
// start=false: stop process
uint16_t zeit=hwapi_shutterTime;
zeit/=100;
sendFDcmd_set(CMD2DC_SHUTTER_COIN, 0,0,uint8_t(start), uint8_t(zeit),0,0);
}
void hwapi::shut_sendOpeningTime(uint16_t timeIn_ms ) const
{
// after this time without retrigger the flap is closed
hwapi_shutterTime=timeIn_ms;
}
void hwapi::esc_takeMoney(void) const
{
// and close automatically after escrow time (1s)
sendFDcmd_set(CMD2DC_ESCR_TAKE,0,0,0,0,0,0);
}
void hwapi::esc_returnMoney(void) const
{
// and close automatically after time
sendFDcmd_set(CMD2DC_ESCR_RETURN,0,0,0,0,0,0);
}
// ----------------------------------------------------------------------------------------------------------
// --------------------------------------------- MIFARE -----------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
// fixed, 8.9.23
uint8_t hwapi::mif_returnReaderStateAndCardType(uint8_t *buf, uint8_t maxBufferSize) const
{
// retval 0=OK 1=error
if (maxBufferSize<64)
return 0;
epi_restoreMifHwData(buf, 64);
return 0;
}
bool hwapi::mif_readerIsOK(void) const
{
// return true if mifare reader is power, serial connected and is the correct one
uint8_t mifData[66];
epi_restoreMifHwData(mifData, 66);
/* stand 8.9.23
struct T_Mifare
{
UCHAR ReaderState; // 1: OK 0: not OK
UCHAR res1;
2: UCHAR ReaderVersion[10];
12: UCHAR CardPresent;
UCHAR CardSelected;
UCHAR Cardtype;
UCHAR CardAllowed; // 0,1 nur Mifare Classic 1k und 4k zugelassen
UCHAR CardSize; // 1 or 4 (kB)
UCHAR LengOfUid; // 4 or 7 (byte)
18: UCHAR UID[8]; // 4 byte oder 7 byte, Format binär
// 26 byte bis hier
UCHAR res2;
UCHAR res3;
28: ULONG UidH; // bei 4byte Uid alles 0
ULONG UidL;
36: UCHAR SectorLogged; // result of loggin: 2=success 3=failed 1=no_tag 8=addr overflow F0=wrongCmd
UCHAR CurrentSector;
UCHAR RD_WR_Result;
UCHAR res4;
// 40byte lang
};
*/
if (mifData[0]==0)
return false;
// Type=currently "SL025-1.8"
if (mifData[2]=='S' && mifData[3]=='L' && mifData[4]=='0' && mifData[5]=='2' && mifData[6]=='5' )
return true;
return false;
}
bool hwapi::mif_cardAttached(void) const // gefixt am 8.9.23
{
return mif_cardIsAttached();
}
uint8_t hwapi::mif_readResult(void) const // geht nicht
{
// 1: read card successful 0: not
uint8_t mifData[66];
epi_restoreMifHwData(mifData, 66);
/* stand 8.9.23
struct T_Mifare
{
UCHAR ReaderState; // 1: OK 0: not OK
UCHAR res1;
2: UCHAR ReaderVersion[10];
12: UCHAR CardPresent;
UCHAR CardSelected;
UCHAR Cardtype;
UCHAR CardAllowed; // 0,1 nur Mifare Classic 1k und 4k zugelassen
UCHAR CardSize; // 1 or 4 (kB)
UCHAR LengOfUid; // 4 or 7 (byte)
18: UCHAR UID[8]; // 4 byte oder 7 byte, Format binär
// 26 byte bis hier
UCHAR res2;
UCHAR res3;
28: ULONG UidH; // bei 4byte Uid alles 0
ULONG UidL;
36: UCHAR SectorLogged; // result of loggin: 2=success 3=failed 1=no_tag 8=addr overflow F0=wrongCmd
UCHAR CurrentSector;
UCHAR RD_WR_Result;
UCHAR res4;
// 40byte lang
};
*/
if (mifData[12]>0 && mifData[15]>0 && (mifData[16]==1 || mifData[16]==4) && (mifData[17]==4 || mifData[17]==7))
return 1;
return 0; // error
}
QString hwapi::mif_cardUID(void) const // OK
{
// new, 8.9.23, works
QString myStr;
uint8_t mifData[66];
epi_restoreMifHwData(mifData, 66);
myStr.clear();
// UID in buf[18...25]
for (int ii=0;ii<8; ii++)
{
myStr+=QString::number(mifData[ii+18],16);
myStr+=" "; // make a gap between numbers
}
return myStr;
}
uint8_t hwapi::mif_getCardDataDec(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize) const
{
// come in with cmd 28
return blkNr+buf[0]+maxBufferSize; // just to get rid of warning
}
QString hwapi::mif_getCardDataStr(uint8_t blockNumber) const
{
// come in with cmd 28
// with blockNumber=0...11
QString myStr;
myStr.clear();
if (blockNumber>11)
return myStr;
else
return myStr;
}
// ----------------------------------------------------------------------------------------------------------
// --------------------------------------------- PRINTER ----------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
// already above:
// void hwapi::prn_switchPower(bool on) 0x2A01
// bool hwapi::prn_readyINisActive(void)
// bool hwapi::prn_isPrinterPowerOn(void)
// void hwapi::request_PrinterHwState() 0x2A02
// void hwapi::request_PrinterCurrentFonts() 0x2A12
// void hwapi::request_PrinterStateComplete() // =request_PrinterHwState + request_PrinterCurrentFonts
uint8_t hwapi::prn_getHwState(struct Tprn_hw_state *prn_hw_state) const
{
// return printer hardware state: power is on? rs-driver on? rs_switch ok? hw-ready-line ok?
// printer on error or ok?
return runProcess->prn_getHwState(prn_hw_state);
}
bool hwapi::prn_isUpAndReady(void) const
{
// 25.5.2023: geht nicht richtig :( bringt immer false obwohl Drucker OK
struct Tprn_hw_state prnHwNow;
prn_getHwState(&prnHwNow);
if (prnHwNow.inIdle && prnHwNow.rsSwOk && prnHwNow.rsDrvOk && prnHwNow.powerRdBk )
return true;
return false;
}
void hwapi::prn_getCurrentFontSetting(struct Tprn_currentSettings *prn_fonts) const
{
uint8_t prnFonts[22];
epi_restorePrinterFonts(&prnFonts[0]);
prn_fonts->currFont = prnFonts[0];
prn_fonts->currSize = prnFonts[1];
prn_fonts->currHeigth= prnFonts[2];
prn_fonts->currWidth = prnFonts[3];
prn_fonts->nowBold = prnFonts[4];
prn_fonts->nowInvers = prnFonts[5];
prn_fonts->nowUnderlined= prnFonts[6];
prn_fonts->currDensity = prnFonts[7];
prn_fonts->currSpeed = prnFonts[8];
prn_fonts->nowAligned = prnFonts[9];
}
void hwapi::prn_sendText(QByteArray *buf) const
{
uint16_t nn, pp, mm, leng_byt, leng_blk, llb, freeStak;
uint8_t tmp66[66];
qCritical() << __PRETTY_FUNCTION__ << "RESET DC DATA VALID";
epi_clearDynMachineConditions(); // 24.6.23
gpi_storeDcDataValid(0);
// komplett aendern 11.9.23
memset(tmp66,0,66);
leng_byt=buf->size();
freeStak=check4freeFDstack();
freeStak<<=6;
if ( leng_byt > freeStak)
{
leng_byt=freeStak; // shorten the buffer as we cannot return an error (void function)
}
llb=leng_byt % 64; // length of last block, >0 if not dividable by 64
leng_blk=leng_byt / 64;
pp=0;
for (nn=0; nn<leng_blk; nn++)
{
for (mm=0; mm<64; mm++)
tmp66[mm]=buf->at(pp++);
longFDcmd_set(CMD2DC_PRI_PRINT_TXT, 0,0,64, tmp66);
}
if (llb>0)
{
//leng_blk++; // z.B. 200 = 3 volle blocks und ein block mit nur 8byte
memset(tmp66,0,66);
for (mm=0; mm<llb; mm++)
tmp66[mm]=buf->at(pp++);
for (mm=llb; mm<64; mm++)
tmp66[mm]=0;
longFDcmd_set(CMD2DC_PRI_PRINT_TXT, 0,0,64, tmp66);
}
}
void hwapi::prn_sendPrnSysCmd(uint8_t para1, uint8_t para2, uint32_t para3) const
{
// send three byte through to printer, see printers manual
//sendWRcmd _setSendCommand8(SENDDIRCMD_PRN_SYS_CMD, para1, para2, 0, para3); hat gar nicht funktioniert
uint8_t data[64];
uint32_t ultmp=para3;
memset(data, 0,64);
data[0]=para1;
data[1]=para2;
data[2]=0;
data[3]=0;
data[4]=uint8_t(ultmp); ultmp>>=8;
data[5]=uint8_t(ultmp); ultmp>>=8;
data[6]=uint8_t(ultmp); ultmp>>=8;
data[7]=uint8_t(ultmp);
longFDcmd_set(CMD2DC_PRI_SYS_CMD, 0, 0, 8, data);
// getestet auf richtige uebertragung am 11.9.23TS
}
void hwapi::prn_sendPrnEscCmd(uint8_t para1, uint8_t para2, uint8_t para3, uint8_t para4) const
{
// send four byte through to printer, see printers manual
sendFDcmd_set(CMD2DC_PRI_ESC_CMD, 0,0, para1, para2, para3, para4);
}
void hwapi::prn_sendPrnSetup(uint16_t paperSpeed, uint8_t density, uint8_t alignment, uint8_t orientation) const
{
// send 5 byte: byte 0,1: speed 5...250 mm/s
// byte2: density 0....(25)....50
// byte3: alignment 'l', 'c', 'r' = left, center, right
// byte4: orientation 0, 90, 180 = 0°, 90°, 180° rotation (by now not supported!)
// not batched! don't use twice within 100ms
uint8_t buf[10];
uint16_t uitmp;
uitmp=paperSpeed;
buf[0]=uint8_t(uitmp);
uitmp>>=8;
buf[1]=uint8_t(uitmp);
buf[2]=density;
buf[3]=alignment;
buf[4]=orientation;
buf[5]=0;
longFDcmd_set(CMD2DC_PRI_SETUP,0,0,5, buf);
}
void hwapi::prn_movePaper(uint8_t wayInMm, uint8_t direction) const
{
//direction: 1=forward 2=backward
sendFDcmd_set(CMD2DC_PRI_MOVE, 0,0, wayInMm, direction, 0,0);
}
void hwapi::prn_setFonts(uint8_t font, uint8_t size, uint8_t width, uint8_t height) const
{
// font = kind of font 0...8
// size = 6...20, 9..9: too tiny 10: small ...12 = normal size ...20=huge
// width: 0...4 0=1x 1=2x 2=4x (huge!) 3=8x 4=16x (3,4 make no sense)
// heigth: 0...7 = 1x...8x only 0,1,2,(3) make sense
sendFDcmd_set(CMD2DC_PRI_SETFONT, 0,0, font, size, width, height);
}
void hwapi::prn_setLetters(uint8_t bold, uint8_t invers, uint8_t underlined) const
{
sendFDcmd_set(CMD2DC_PRI_SETLETTER, 0, 0, bold, invers, underlined, 0);
}
void hwapi::prn_cut(uint8_t kindof) const
{
// kindof = 1: full cut 2: partial cut 3=eject (5xLF + full cut)
sendFDcmd_set(CMD2DC_PRI_CUT, 0,0, kindof,0,0,0);
}
void hwapi::prn_newLine(uint8_t nrOfLines) const
{
sendFDcmd_set(CMD2DC_PRI_LF, 0,0, nrOfLines, 0, 0, 0);
}
void hwapi::prn_printCompleteFontTable(void) const
{
sendFDcmd_set(CMD2DC_PRI_PRIFONTTABLE,0,0,0,0,0,0);
}
void hwapi::prn_printBarcode(uint8_t kindOf, uint8_t withText, uint8_t offset, uint8_t rotation, uint8_t dataLeng, uint8_t *data) const
{
uint8_t buf[66], nn;
//uint16_t uitmp;
if (dataLeng>58)
dataLeng=58;
buf[0]=kindOf;
buf[1]=withText;
buf[2]=offset;
buf[3]=rotation;
buf[4]=dataLeng;
// rest: Barcode-data:
for (nn=0; nn<dataLeng; nn++)
buf[5+nn]=data[nn];
longFDcmd_set(CMD2DC_PRI_BARCODE,0,0,(5+dataLeng), buf);
}
void hwapi::prn_sendQRdata(QByteArray *buf) const
{
// maximal 150 alphanummeric bytes
buf->clear();
}
void hwapi::prn_printQRcode(void) const
{
// which was sent before
sendFDcmd_set(CMD2DC_PRI_QR_CODE,0,0,0,0,0,0);
}
void hwapi::prn_printLogo(uint8_t nrOfLogo, uint8_t offset ) const
{
sendFDcmd_set(CMD2DC_PRI_LOGOFROMFLASH, 0,0, nrOfLogo, offset, 0, 0);
}
// .........................................................
// Parking Ticket (print out) designer - obsolete
// .........................................................
/*
static QByteArray ticketTemplate;
void hwapi::pri_startTicketDesign(void) const
{
ticketTemplate.clear();
}
int hwapi::pri_TD_getCurrentSize(void) const
{
return ticketTemplate.size();
}
bool hwapi::pri_TD_addText(QByteArray text) const
{
if ((ticketTemplate.length() + text.length())>1278)
return false;
ticketTemplate.append(text);
qDebug()<<"\nText added "<<ticketTemplate;
return true;
}
bool hwapi::pri_TD_addValue(int val) const
{
// QString tmpStr;
QByteArray tmpStr;
tmpStr.setNum(val,10); // up to 12 chars
if (ticketTemplate.length()>1266)
return false;
ticketTemplate.append(tmpStr);
return true;
}
*/
//bool hwapi::pri_TD_addCommand(char group, char attribute, char p1, char p2, char p3, char p4, char p5) const
//{
// always add 8 byte to the ticket layout: ESC & group & attribute & parameter1...5
/*
char tmpStr[10];
// command has always fixed length of 8 byte
if (ticketTemplate.length()>1270)
return false;
if (group<50 || group>59)
return false;
if (attribute<10 || attribute>30)
return false;
tmpStr[0]=0x1B; // ESC
tmpStr[1]=group;
tmpStr[2]=attribute;
tmpStr[3]=p1;
tmpStr[4]=p2;
tmpStr[5]=p3;
tmpStr[6]=p4;
tmpStr[7]=p5;
ticketTemplate.append(tmpStr, 8);
qDebug()<<"\ncmd added "<<ticketTemplate;
return true;
}
bool hwapi::pri_TD_addNewLine(void) const
{
if (ticketTemplate.length()>1277)
return false;
ticketTemplate.append("\n");
return true;
}
bool hwapi::pri_TD_addSign(char sign) const
{
if (ticketTemplate.length()>1277)
return false;
ticketTemplate.append(sign);
return true;
}
char hwapi::prn_clearDocument(uint8_t documentNumber) const
{
if (documentNumber>15)
return false;
sendWRcmd_ setSendCommand4(SENDDIRCMD_PRN_CLEARDOC, documentNumber, 0, 0, 0);
CMD2DC_PRI_CLEAR_DOC
return true;
}
bool hwapi::prn_store_Document(uint8_t documentNumber ) const
{
// send to DC
// documentNumber=0...15, stored in Eeprom
// maximal 1280 bytes each
// allowed: 0x20...0xFF, 0x0A, 0x0C, 0x1B (LF, CR, Esc)
// 0x1B=start of embedded command (next 7bytes = command)
if (documentNumber>15)
return false;
sub_storeSendingText(&ticketTemplate);
epi_storeUserOfSendingTextBuffer(3,documentNumber,0,0,0); // 3=store document
return true;
}
bool hwapi::prn_printDocument(uint8_t documentNumber, struct T_dynDat *dynTicketData) const
{
if (documentNumber>15)
return false;
epi_store64ByteSendData(64, &(dynTicketData->licensePlate[0]));
sendWRcmd_ setSendCommand4(SENDDIRCMD_PRN_DOC, documentNumber, 0, 0, 0);
return true;
}
*/
// ----------------------------------------------------------------------------------------------------------
// ------------------------------------------- MDB Bus ------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
void hwapi::mdb_sendBusReset(void) const
{
//sendWRcmd_ setSendCommand4(SENDDIRCMD_MDB_RES, 0,0,0,0);
sendFDcmd_set(CMD2DC_MDB_DORESET, 0,0, 0,0,0,0);
}
#define mdb_device_coinChk 0
#define mdb_device_changer 1
#define mdb_device_bill 2
//#define mdb_device_credit 3 // obsolete
void hwapi::mdb_sendCommand(uint8_t toMdbDevice, uint8_t mdbCommand) const
{
//sendWRcmd _setSendCommand4(SENDDIRCMD_MDB_SENDCMD, toMdbDevice, mdbCommand, 0,0);
sendFDcmd_set(CMD2DC_MDB_SENDCMD, 0,0, toMdbDevice, mdbCommand, 0,0);
}
void hwapi::mdb_sendMessage(uint8_t toMdbDevice, uint8_t mdbCommand, uint8_t nrOfData, uint8_t *dataBuffer) const
{
// nrOfData = sizeOf(dataBuffer) maximal 34 byte according mdb specs
uint8_t myBuf[64], ii;
tslib_strclr(myBuf, 0, 64);
myBuf[0]=toMdbDevice;
myBuf[1]=mdbCommand;
if (nrOfData>34) nrOfData=34;
myBuf[2]=nrOfData;
for (ii=0; ii<nrOfData; ii++)
myBuf[ii+3]=dataBuffer[ii];
//epi_store64ByteSendData(37, myBuf);
//sendWRcmd_setSendCommand0(SENDDIRCMD_MDB_SNDMSG);
longFDcmd_set( CMD2DC_MDB_SENDMSG,0,0,37,myBuf);
}
bool hwapi::mdb_busIsReadyToWork() const
{
return epi_restoreMdbBusReady();
}
bool hwapi::mdb_deviceVoltageOK() const
{
return epi_restoreMdbV12Ready();
}
bool hwapi::mdb_busVoltageOk() const
{
return epi_restoreMdbV5Ready();
}
uint8_t hwapi::mdb_getLastDeviceResponse(uint8_t *fromDevice, uint8_t *lastRequest,
uint8_t *responseLength, uint8_t *responseBuffer) const
{
// fromDevice: device nr from which data was requested 0,1,2,3
// lastRequest: sent mdb command
// responseLength: nr of payload data (after mdb-ack) 0...34
// responseBuffer holds payload data (answer from mdb device)
// return val: mdb result of this request: 1=got ACK 2=got 3xNAK 3=no or bad response 4:got Data (after ACK)
uint8_t leng, ResData[64];
epi_restoreMdbResponse(&leng, ResData);
// last received mdb answer (from mdb device)
// only needed if a special command was sent directly
// DB0: mdb Device-Nr
// DB1: last sent mdb command
// DB2: lastResult 1=got ACK 2=got 3xNAK 3=no or bad response 4:got Data (after ACK)
// DB3: nr of received (payload) data bytes (apart from ACK, can be 0....34)
// DB4...DB39: rec.data (payload)
*fromDevice=ResData[0];
*lastRequest=ResData[1];
*responseLength=ResData[3];
tslib_strcpy(&ResData[4], responseBuffer, ResData[3]);
return ResData[2];
}
// ----------------------------------------------------------------------------------------------------------
// ---------------------------------- Electronic Coin Validator EMP -----------------------------------------
// ----------------------------------------------------------------------------------------------------------
void hwapi::emp_sendSettings(uint16_t coinAcceptance, uint8_t tokenChannel, uint16_t *coinDenomination ) const
{
// coinAcceptance: bit0=coin1 (lowest denomination) bit15=coin16 bitH=accept bit L = deny coin (no validation)
// tokenChannel 0...31: if this signal comes from emp then a token was inserted
// coinDenomination = array of 16 coin values (e.g. 5, 10, 20...)
uint8_t myBuf[64], ii, pp;
uint16_t uitmp=coinAcceptance;
tslib_strclr(myBuf, 0, 64);
myBuf[0]=uint8_t (uitmp);
uitmp>>=8;
myBuf[1]=uint8_t (uitmp);
myBuf[2]=tokenChannel;
pp=3;
for (ii=0; ii<16; ii++)
{
uitmp=coinDenomination[ii];
myBuf[pp]=uint8_t(uitmp);
uitmp>>=8;
myBuf[pp+1]=uint8_t(uitmp);
pp+=2;
}
longFDcmd_set(CMD2DC_EMP_SET,0,0,35, myBuf);
}
void hwapi::emp_pollingOnOff(uint8_t on) const
{
// on: 1=start polling the coin accepter 0=stop
sendFDcmd_set(CMD2DC_EMP_STARTPOLL, 0,0, on,0,0,0);
}
void hwapi::emp_startCoinAcceptance(void) const
{
sendFDcmd_set(CMD2DC_EMP_STARTPAY, 0,0, 0,0,0,0);
}
void hwapi::emp_stopCoinAcceptance(void) const
{
sendFDcmd_set(CMD2DC_EMP_STOPPAY, 0,0, 0,0,0,0);
}
void hwapi::emp_getAllParameters(struct T_emp *emp) const
{
uint8_t leng, data[66], ii, pp;
epi_restoreEmpSettings(&leng, data); // expected length = 64 byte
// get 64 bytes about EMP: see h-file
emp->gotSetup = data[0];
emp->state = data[1];
emp->shaft = data[2];
emp->countryCode= uchar2uint(data[4], data[3]);
emp->scale = data[5];
emp->decimals = data[6];
for (ii=0; ii<16; ii++)
emp->coinValues[ii] = data[7+ii];
emp->coinAccept = uchar2uint(data[24], data[23]);
emp->tokenChannel = data[25];
emp->pollingRunning = data[26];
emp->paymentRunning = data[27];
pp=28;
for (ii=0; ii<16; ii++)
{
emp->denomination[ii] = uchar2uint(data[pp+1], data[pp]);
pp+=2;
}
emp->routing= uchar2uint(data[61], data[60]);
}
uint8_t hwapi::emp_chkIfCoinInserted(void) const
{
// retval: 0...16 coins left in FIFO
return epi_isNewCoinLeft();
}
void hwapi::emp_getNewCoinRecord(uint8_t *valid, uint8_t *signal, uint8_t *error, uint16_t *value) const
{
epi_restoreEmpCoinSignal(valid, signal, error, value);
}
uint8_t hwapi::emp_giveLastCoin(uint16_t *value, uint8_t *signal) const
{
// retval: 0: NO coin stored 1: valid coin 2: got wrong coin or coin denied
// value: if retval1: value of the coin if reval=2: error number
// signal: channel nr reported from checker
uint8_t valid, chan, error;
uint16_t wert;
epi_restoreEmpCoinSignal(&valid, &chan, &error, &wert);
if (valid && error==0xFF )
{
*value=wert;
*signal=chan;
return 1;
}
if (valid && error<0xFF )
{
*value=error;
*signal=chan; // normally 0, but sometimes we get both
return 2;
}
return 0;
}
uint8_t hwapi::emp_returnLastCoin(uint16_t *value, uint8_t *signal) const
{
// use this for coin changer
uint8_t valid, chan, error;
uint16_t wert;
epi_restoreEmpCoinSignal(&valid, &chan, &error, &wert);
if (error)
{
*value=0;
*signal=error;
return 0;
}
*value=wert;
*signal=chan;
return valid;
}
QString hwapi::dc_getTxt4RsDiagWin(void) const
{
#ifdef THIS_IS_CA_MASTER
return epi_getTxt4RsDiagWin();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clrTxt4RsDiagWin(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clrTxt4RsDiagWin();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
QString hwapi::dc_get2ndTxt4RsDiagWin(void) const
{
#ifdef THIS_IS_CA_MASTER
return epi_get2ndTxt4RsDiagWin();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clr2ndTxt4RsDiagWin(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clr2ndTxt4RsDiagWin();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
QString hwapi::dc_getTxt4HsStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
// Crash!
return epi_getTxt4HsStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clrTxt4HsStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clrTxt4HsStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
QString hwapi::dc_getTxt4masterStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
return epi_getTxt4masterStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clrTxt4masterStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clrTxt4masterStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
QString hwapi::dc_getTxt4resultStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
return epi_getTxt4resultStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clrTxt4resultStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clrTxt4resultStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
QString hwapi::dc_getdataStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
return epi_getTxt4dataStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clrTxt4dataStateLine(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clrTxt4dataStateLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
QString hwapi::dc_getdatifLine(void) const
{
#ifdef THIS_IS_CA_MASTER
return epi_getTxt4datifLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
return "";
#endif
}
void hwapi::dc_clrTxt4datifLine(void) const
{
#ifdef THIS_IS_CA_MASTER
epi_clrTxt4datifLine();
#else
qCritical()<<"hwapi: error CAslave cannot use serial";
#endif
}
// ----------------------------------------------------------------------------------------------------------
// -------- DC Bootloader 1.Version // obsolete
// ----------------------------------------------------------------------------------------------------------
// obsolete
void hwapi::bl_iniChain(void) const
{
}
// obsolete
bool hwapi::bl_importBinFile(QByteArray readBinFile, uint32_t fileSize, char withDispl) const
{
// copy file from QByteArray into local buffer for sending to DC
// calculate size, nr_of_blocks and crc
// just for special usage
return dcBL_importBinFile(readBinFile, fileSize, withDispl);
}
// obsolete
uint8_t hwapi::bl_activatBootloader(uint8_t *sendData) const
{
//return dcBL_activatBootloader(sendData);
// just for special usage
return sendData[0];
}
// obsolete
uint8_t hwapi::bl_startChain(void) const
{
// obsolete
//return dcBL_startChain();
return 0;
}
// obsolete
uint8_t hwapi::bl_readBLversion(uint8_t *sendData) const
{
// minimum size of sendData-buffer: 5byte retval: length
// just for special usage
return dcBL_readBLversion(sendData);
}
// obsolete
uint8_t hwapi::bl_readFWversion(uint8_t *sendData) const
{
// minimum size of sendData-buffer: 5byte retval: length
return dcBL_readFWversion(sendData);
}
// obsolete
uint8_t hwapi::bl_prepareDC_BLcmd(uint8_t Cmd, uint8_t SendDataLength, uint8_t *sendData, uint8_t *outBuf) const
{
// just for very special usage
// make BL protocol, retval = outbuf length (5...133)
// bring data in correct form: start always with 0x02 finish with 0x03 and append checksum
// 0x02 Cmd < ...sendData ..> CRC CRC 0x03
// Data length = 0...64
// special conversion: if data contain 2 or 3 (STX, ETX) then write two bytes: 0x1B (=ESC) and data|0x80
// so maxlength = 5 + 2 x 64 (if all data are 2 or 3) without 2,3: maxlength = 5 + 64
return dcBL_prepareDC_BLcmd(Cmd, SendDataLength, sendData, outBuf);
}
// obsolete
uint8_t hwapi::bl_exitBL(uint8_t *sendData) const
{
// returns command to be sent to DC-BL in order to stop the BL
// just for very special usage
// minimum size of sendData-buffer: 5byte retval: length
return dcBL_exitBL(sendData);
}
// obsolete
void hwapi::led_switchLedIllumination(uint8_t on) const
{
sendFDcmd_set(CMD2DC_LED_IN, CMD2DC_RdBkAllOutputs, 0, on, 0, 0, 0);
}
// ------------------------------------------------------------------------------------
// 27.3.2023: Use Device-Controller's Bootloader to send hex-file
// ------------------------------------------------------------------------------------
void hwapi::bl_rebootDC(void) const // tested 26.09.2023
{
// send command to normal DC-Program requesting a restart
// BL is working for 5s after power-on-reset.
runProcess->bl_rebootDC();
}
void hwapi::bl_startBL(void) const // tested 26.09.2023
{
// use this function within the first 5s after reboot to startup the BL,
// otherwise the BL jumps to normal DC application
runProcess->bl_startBL();
}
void hwapi::bl_checkBL(void) const // tested 26.09.2023
{
// call this function in order to get information, afterwards use "bl_isUp()"
runProcess->bl_checkBL();
}
bool hwapi::bl_isUp(void) const // tested 26.09.2023
{
return runProcess->bl_isUp();
}
// obsolete, better use auto function listed further down
void hwapi::bl_sendAddress(uint16_t blockNumber) const
{
// send start address, nr of 64byte-block, start with 0
// will be sent only for folling block-numbers:
// 0, 1024, 2048, 3072 and 4096, so basically every 64kByte
uint32_t dcBL_BlkCtr=(uint32_t)blockNumber;
uint8_t len, buf[20];
tslib_strclr(buf, 0, 20);
if (dcBL_BlkCtr==0 || dcBL_BlkCtr==1024 || dcBL_BlkCtr==2048 || dcBL_BlkCtr==3072 || dcBL_BlkCtr==4096)
{
dcBL_BlkCtr*=64;
len=dcBL_sendFlashStartAddr2BL(dcBL_BlkCtr, buf); // make command string
// minimum size of sendData-buffer: 13byte retval: length (9...13)
sendWRcmd_setSendBlock160(len, buf); // send command to BL
}
}
// obsolete, better use auto function listed further down
uint8_t hwapi::bl_wasSendingAddOK(void) const
{
// return val: 0: no response by now 1:error 10: OK
return dcBL_sendSuccess(0x21);
}
void hwapi::bl_openBinary(void) const
{
}
// obsolete, better use auto function listed further down
void hwapi::bl_sendDataBlock(uint8_t length, uint8_t *buffer) const
{
// send 64 byte from bin file
uint8_t LL=length, sendBuf[80], sendLen;
if (LL>64) LL=64;
tslib_strclr(sendBuf,0,80);
sendLen=dcBL_prepareDC_BLcmd(0x22, LL, buffer, sendBuf); // pack into protocol frame
sendWRcmd_setSendBlock160(sendLen, sendBuf); // send 140 bytes
delay(100);
}
// obsolete, better use auto function listed further down
void hwapi::bl_sendLastBlock(void) const
{
uint8_t len, buf[20];
len=dcBL_writeLastPage(buf);
sendWRcmd_setSendBlock160(len, buf);
}
// obsolete, better use auto function listed further down
uint8_t hwapi::bl_wasSendingDataOK(void) const
{
// return val: 0: no response by now 1:error 10: OK
return dcBL_sendSuccess(0x22);
}
void hwapi::bl_stopBL(void) const // tested 26.09.2023
{
uint8_t len, buf[20];
len=dcBL_exitBL(buf);
sendWRcmd_setSendBlock160(len, buf);
epi_setNowIsBootload(false);
}
// ------------------------------------------------------------------------------------
// 6.4.2023: new functions for coin collection and printing
// some new system functions
// ------------------------------------------------------------------------------------
// use:
// bool sendFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t dat1, uint8_t dat2, uint8_t dat3, uint8_t dat4);
// write Command to memory, wait for transport
// bool longFDcmd_set(uint8_t nextWrCmd, uint8_t nextRdCmd, uint8_t blockNum, uint8_t length, uint8_t *data);
// write Command to memory, wait for transport
// data buffer size always 64! data[64], padded with 0
bool hwapi::rtc_setTimeDateDirect(struct Trtc_DateTime *DateTime) const
{
// return true if successful. could fail if more the 8 commands are waiting
uint8_t temp[66];
bool b_ret;
/* in interfaces.h:
struct Trtc_DateTime
{
uint8_t rtc_hour;
uint8_t rtc_min;
uint8_t rtc_sec;
uint8_t rtc_dayOfMonth;
uint8_t rtc_month;
uint8_t rtc_year;
uint8_t rtc_dayOfWeek;
};
*/
tslib_strclr(temp,0,66);
temp[0]= DateTime->rtc_hour;
temp[1]= DateTime->rtc_min;
temp[2]= DateTime->rtc_sec;
temp[3]= 20;
temp[4]= DateTime->rtc_year;
temp[5]= DateTime->rtc_month;
temp[6]= DateTime->rtc_dayOfMonth;
temp[7]= DateTime->rtc_dayOfWeek;
b_ret=longFDcmd_set(20,0,0,8,temp);
return b_ret;
}
bool hwapi::rtc_getExtendedTime(uint8_t *leng, uint8_t *data) const
{
epi_restoreExtendedTime(leng, data);
return true;
/*
buf[0]=GlobTime.Hours;
buf[1]=GlobTime.Min;
buf[2]=GlobTime.Sec;
buf[3]=GlobTime.Year;
buf[4]=GlobTime.Month;
buf[5]=GlobTime.Day;
buf[6]=GlobTime.DOW;
buf[7]=' '; // immer auf 32bit auffüllen sonst Speicherproblem beim Master!
uitmp=GlobTime.MinOfDay;
buf[8]=swl_getOneByteFromUint(uitmp, 0);
buf[9]=swl_getOneByteFromUint(uitmp, 1);
buf[10]=' ';
buf[11]=' ';
ultmp=GlobTime.SecOfDay;
buf[12]=swl_getOneByteFromUlong(ultmp, 0);
buf[13]=swl_getOneByteFromUlong(ultmp, 1);
buf[14]=swl_getOneByteFromUlong(ultmp, 2);
buf[15]=swl_getOneByteFromUlong(ultmp, 3);
buf[16]=swl_isLeap(GlobTime.Year);
buf[17]=swl_getNextLeapYear(GlobTime.Year);
buf[18]=swl_getLastLeapYear(GlobTime.Year);
buf[19]=swl_hoursOfThisWeek(GlobTime.DOW, GlobTime.Hours);
uitmp=swl_minutesOfThisWeek(GlobTime.DOW, GlobTime.Hours, GlobTime.Min);
buf[20]=swl_getOneByteFromUint(uitmp, 0); // 0=low byte 1=high byte
buf[21]=swl_getOneByteFromUint(uitmp, 1);
uitmp=swl_hoursOfThisMonth(GlobTime.Day, GlobTime.Hours);
buf[22]=swl_getOneByteFromUint(uitmp, 0);
buf[23]=swl_getOneByteFromUint(uitmp, 1);
uitmp=swl_minutesOfThisMonth(GlobTime.Day, GlobTime.Hours, GlobTime.Min);
buf[24]=swl_getOneByteFromUint(uitmp, 0);
buf[25]=swl_getOneByteFromUint(uitmp, 1);
uitmp=swl_GetDaysOfYear(GlobTime.Year, GlobTime.Month, GlobTime.Day);
buf[26]=swl_getOneByteFromUint(uitmp, 0);
buf[27]=swl_getOneByteFromUint(uitmp, 1);
uitmp=swl_GetHoursOfYear(GlobTime.Year, GlobTime.Month, GlobTime.Day, GlobTime.Hours);
buf[28]=swl_getOneByteFromUint(uitmp, 0);
buf[29]=swl_getOneByteFromUint(uitmp, 1);
buf[30]=0;
buf[31]=0;
ultmp= swl_GetMinutesOfYear(GlobTime.Year, GlobTime.Month, GlobTime.Day,
GlobTime.Hours, GlobTime.Min);
buf[32]=swl_getOneByteFromUlong(ultmp, 0);
buf[33]=swl_getOneByteFromUlong(ultmp, 1);
buf[34]=swl_getOneByteFromUlong(ultmp, 2);
buf[35]=swl_getOneByteFromUlong(ultmp, 3);
buf[36]=rtc_getSqwaveSettings();
buf[37]=0;
buf[38]=0;
buf[39]=0;
ultmp= 0; // Minutes of the Millenium
buf[40]=swl_getOneByteFromUlong(ultmp, 0);
buf[41]=swl_getOneByteFromUlong(ultmp, 1);
buf[42]=swl_getOneByteFromUlong(ultmp, 2);
buf[43]=swl_getOneByteFromUlong(ultmp, 3);
dc2prot_setReadData(44, buf);
*/
}
bool hwapi::rtc_getExtendedTime(struct T_extTime *exTime) const
{
uint8_t len;
uint16_t LL, nn;
uint8_t *start;
uint8_t buf[66];
epi_restoreExtendedTime(&len, buf);
// Puffer in struct eintragen:
LL=sizeof(struct T_extTime);
start = &(exTime->Hours);
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
return true;
}
bool hwapi::sys_runCompleteTest(void) const
{
// warning: lasts 20s in one pace
return sendFDcmd_set(149, 0,0, 0,0,0,0);
}
bool hwapi::sys_ready4sending(void) const
{
// return true if a Json-file can be sent
// check free memory
uint8_t frei=check4freeFDstack();
// Command-Stack sollte 16 Commands fassen, je 64byte Nutzdaten = 1024byte
// frei gibt also die Anzahl freier 64byte Bloecke zurueck
// das Json-File hat max 800 byte = 13 bloecke
if (frei<16) // Puffer muss ganz leer sein! nicht dass was durcheinander kommt
return false;
return true;
}
bool hwapi::sys_sendJsonFileToDc(uint8_t kindOfFile, uint8_t nrOfTemplate, uint8_t *content ) const
{
// kindOfFile: 1=config, 2=device, 3=cash, 4=serial, 5=time, 6=printer
// nrOfTemplate=1...32 if kindOfFile==6
// content = content of the Json file, max 800byte ascii signs
// file is 0-terminated
// return false if sending is not possible, wait a second
uint8_t dateiArt, NummDesTempl;
uint8_t inhaltOfJson[802], temp[66];
uint16_t dateiLang, uitmp;
uint8_t nrOfBlocks;
uint8_t frei, bn=0;
dateiArt=kindOfFile;
NummDesTempl=nrOfTemplate;
tslib_strclr(inhaltOfJson,0,801);
dateiLang=tslib_strlen(content);
if (dateiLang>800) dateiLang=800;
tslib_strcpy(content, inhaltOfJson, dateiLang); // enthaelt genaue Laenge, Rest =0
nrOfBlocks=dateiLang/64;
if (dateiLang%64>0)
nrOfBlocks++;
dateiLang=nrOfBlocks;
dateiLang<<=6; // auf volle 64byte aufgerundet
// check free memory
frei=check4freeFDstack();
// Command-Stack sollte 16 Commands fassen, je 64byte Nutzdaten = 1024byte
// frei gibt also die Anzahl freier 64byte Bloecke zurueck
// das Json-File hat max 800 byte = 13 bloecke
if (frei<16) // Puffer muss ganz leer sein! nicht dass was durcheinander kommt
return false;
// Start- und Stop auch als langes Kommando schicken
// PROBLEM: wuerden sie in einem anderen Batch gespeichert (short command stack),
// dann kann die Reihenfolge nicht gewaehrleistet werden
// Das Startkommando muss sicher zuerst kommen
// Das Abschlusskommando muss sicher zuletzt kommen
tslib_strclr(temp,0,65);
temp[0]=dateiArt;
temp[1]=NummDesTempl;
longFDcmd_set(30, 0,0, 2,temp); // sende "Starte-file-DL"
uitmp=0; bn=0;
do
{
biox_CopyBlock(inhaltOfJson, uitmp, temp, 0, 64);
longFDcmd_set(31,0, bn++, 64, temp);
//uitmp<<=6; // falsch
uitmp+=64;
} while(uitmp < dateiLang);
longFDcmd_set(32, 0,0, 0,temp); // Abschluss
return true;
}
static uint8_t lastSentDynData[64];
//char prn_dynPrnVal[8][8];
bool hwapi::prn_sendDynamicPrnValues(uint8_t *dynPrnVal ) const
{
// dynPrnVal = array of 8 Variables with 8 byte each, come as ascii string
// like: char prn_dynPrnVal[8][8];
// return true if sending, false if cmd-stack is full
//uint8_t temp[66];
//tslib_strcpy(dynPrnVal, temp, 64); // Vorsicht, kann \0en enthalten
memcpy(lastSentDynData, dynPrnVal, 64);
return longFDcmd_set(33,39,0, 64, lastSentDynData);
}
bool hwapi::prn_printTemplate(uint8_t nrOftemplate) const
// print one of the templates loaded by Json prior
// nr = 1..32
{
// return true if sending, false if cmd-stack is full
qCritical() << __PRETTY_FUNCTION__ << "RESET DC DATA VALID";
epi_clearDynMachineConditions(); // 24.6.23
gpi_storeDcDataValid(0);
return sendFDcmd_set(152, 0,0, nrOftemplate,0,0,0);
}
void hwapi::log_getHoldAccountNumbers(uint8_t *nrOfVals, uint16_t *accNr ) const
{
// returns all acc nrs of the backuped vault records
// use: uint16_t backupedAccNumbers[8]
epi_restoreDCbackupAccNr(nrOfVals, accNr);
}
bool hwapi::log_selectVaultRecord(uint16_t accountNr ) const
{
// return true if sending, false if cmd-stack is full
// and trigger transfer
uint8_t dat1, dat2;
bool ret;
uint8_t frei=check4freeFDstack();
if (frei<8)
return false;
sendFDcmd_clrStack();
epi_startSupervision();
epi_iniVRstorage();
dat1=uint2uchar(accountNr, LOWBYTE);
dat2=uint2uchar(accountNr, HIGHBYTE);
ret=sendFDcmd_set(153, 0,0, dat1,dat2,0,0); // select this record
// true means "will be sent"
sendFDcmd_set(0,38,0, 0,0,0,0); // return VaultRecord block-Nr.0
sendFDcmd_set(0,38,1, 0,0,0,0); // return VaultRecord block-Nr.1
sendFDcmd_set(0,38,2, 0,0,0,0); // return VaultRecord block-Nr.2
sendFDcmd_set(0,38,3, 0,0,0,0); // return VaultRecord block-Nr.3
sendFDcmd_set(0,38,4, 0,0,0,0); // return VaultRecord block-Nr.4
sendFDcmd_set(0,38,5, 0,0,0,0); // return VaultRecord block-Nr.5
// 38: <100 to get long 64byte response
return ret;
}
bool hwapi::log_chkIfVaultRecordAvailable(void) const
{
// return true if completly received
if ( epi_checkIfVaultRecordAvailable() )
{
return true;
}
return false;
}
//uint8_t hwapi::log_getAvailableVaultBlocks(void) const
bool hwapi::log_getVaultRecord(struct T_vaultRecord *retVR) const
// which was selected by: log_selectVaultRecord()
// to be forwarded to Ismas
// return true if completly received
{
#define MAXLENOFVAULTREC 400
uint16_t LL, nn, len;
char *start;
uint8_t buf[MAXLENOFVAULTREC];
bool ret;
ret=epi_restoreVaultRecord(&len, buf); // true if completly received
if (ret==false)
return false;
// Puffer in struct eintragen:
LL=sizeof(struct T_vaultRecord);
if (LL>MAXLENOFVAULTREC) LL=MAXLENOFVAULTREC;
start = &retVR->startbuffer[0];
nn=0;
// 14.9.23 neu: Datensatz erst pruefen, [0..3] enthaelt "Psa>" und [4,5 =Abr.Nr]
uint16_t ds_acc_nr=uchar2uint(buf[5], buf[4]);
if (buf[0]=='P' && buf[1]=='s' && buf[2]=='a' && buf[3]=='>' && ds_acc_nr<60000)
{
// valid data, copy data to struct
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
return true;
} else
{
// wrong data, clear struct
do
{
*start = 0;
start++;
} while(++nn<LL);
return false;
}
return false;
}
bool hwapi::prn_printAccountReceipt(void) const
{
qCritical() << __PRETTY_FUNCTION__ << "RESET DC DATA VALID";
epi_clearDynMachineConditions(); // 24.6.23
gpi_storeDcDataValid(0);
return sendFDcmd_set(154, 0,0, 0,0,0,0);
}
bool hwapi::prn_printTestTicket(void) const
{
qCritical() << __PRETTY_FUNCTION__ << "RESET DC DATA VALID";
// return true if sending to DC OK, false if cmd-stack is full
epi_clearDynMachineConditions(); // 24.6.23
gpi_storeDcDataValid(0);
return sendFDcmd_set(157, 0,0, 0,0,0,0);
}
bool hwapi::cash_startPayment(uint32_t amount) const
{
return runProcess->cash_startPayment(amount);
}
uint8_t hwapi::cash_paymentProcessing(void) const
{
// no need to use
// will be called automatically
uint8_t collActiv=0;
collActiv = runProcess->cash_paymentProcessing();
return collActiv;
}
uint32_t hwapi::getInsertedAmount(void) const
{
uint32_t ultmp;
ultmp=epi_CurrentPaymentGetAmount();
if (ultmp>65000) ultmp=0; // 19.6.23
qDebug() << "current inserted amount: "<< ultmp;
return ultmp;
}
uint16_t hwapi::getLastInsertedCoin(void) const
{
uint32_t ultmp;
ultmp=epi_CurrentPaymentGetLastCoin();
qDebug() << "last inserted coin: "<< ultmp;
return ultmp;
}
bool hwapi::getAllInsertedCoins(uint16_t *types, uint16_t *values) const
{
// alle bei diesem Verkauf eingeworfenen Münzen sind gespeichert, max 64
return epi_CurrentPaymentGetAllCoins(types, values);
}
bool hwapi::cash_cancelPayment(void) const
// and return coins
{
// DB1: 1=encash 2=cancel & return coins
// 3=stop and keep coins in escrow
//epi_setNowCoinPay(false); // new since 20.9.23
// am 6.12.23 wieder raus, waehrend Druck und wechseln auch schnell abfragen
//qCritical() << "cash cancel payment and return coins";
return sendFDcmd_set(156, 0,0, 2,0,0,0);
}
bool hwapi::cash_stopPayment(void) const
// and keep coins in escrow
{
// DB1: 1=encash 2=cancel & return coins
// 3=stop and keep coins in escrow
//epi_setNowCoinPay(false); // new since 20.9.23
// am 6.12.23 wieder raus, waehrend Druck und wechseln auch schnell abfragen
//qCritical() << "cash stop payment and keep coins in escrow";
// qCritical() << "emitting signal StopByPushbutton 2";
emit hwapi_payStopByPushbutton();
return sendFDcmd_set(156, 0,0, 3,0,0,0);
}
// after ticket/goods issue:
bool hwapi::vend_success(void) const
// conclude payment process, encash all inserted coins to vault. Printing was successful
// if possible return change
{
// DB1: 1=encash 2=cancel & return coins
// 3=stop and keep coins in escrow
epi_setNowCoinPay(false); // new since 20.9.23
//qCritical() << "printing finished, encash coins";
return sendFDcmd_set(156, 0,0, 1,0,0,0);
}
bool hwapi::vend_failed(void) const
// conclude payment process and return all inserted coins
{
// DB1: 1=encash 2=cancel & return coins
// 3=stop and keep coins in escrow
epi_setNowCoinPay(false); // new since 20.9.23
//qCritical() << "printing failed, encash coins";
return sendFDcmd_set(156, 0,0, 2,0,0,0);
}
// obsolete
uint8_t hwapi::mif_getCardType(QString *cardholder) const
{
// return 1,2,3,4 = upper, lower access card, printer test, coin test
// cardholder: 7byte Name-String
uint8_t type=0, nn; // buf[8],
char ctmp=0;
for (nn=0;nn<8; nn++)
{
cardholder[nn]=ctmp;
}
return type;
}
uint64_t hwapi::sys_getWakeSource(void) const
{
// retval: 6 bytes, bit coded, 1=event keeps DC awake
return epi_getWakeSources();
}
uint8_t hwapi::sys_getWakeReason(void) const
{
// Master was woken by following reason:
// 1: MDB Event
// 2: Coin Event
// ( 3: Master Event) - will not set the wake line
// ( 4: 32s pulse) - will not set the wake line
// 5: Door Event
// ( 6: Diag Event) - will not set the wake line
// 7: 30min-Pulse for HB
return epi_getWakeReason();
}
void hwapi::sys_getDeviceConditions(uint8_t *leng, uint8_t *data) const
{
//uint8_t leng, data[66];
epi_restoreDeviceConditions(leng, data);
}
void hwapi::sys_getDeviceConditions(struct T_moduleCondition *devCond) const
{
uint16_t LL, nn;
uint8_t *start;
uint8_t buf[70], leng;
epi_restoreDeviceConditions(&leng, buf);
// Puffer in struct eintragen:
LL=sizeof(struct T_moduleCondition);
start = &devCond->ram;
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
// patch for printer error, only needed until DC4.37 ------------------------------
struct T_dynamicCondition myDynMachCond;
sys_getDynMachineConditions(&myDynMachCond);
uint8_t zustand=myDynMachCond.lastPrinterStatus;
if (zustand & 0xE0)
// 0: printer OK
// bit0: near paper end bit1: no paper
// bit2: temperature error bit3: error head open
// bit4: paper jam in cutter
// bit6: no response bit7: serial rec. error
// bit5: printer not ready
devCond->printer=200; // not connected
else
if (zustand & 0x1C)
devCond->printer=201; // on error
else
if (zustand & 0x02)
devCond->printer=202; // no paper
else
if (zustand & 0x01)
devCond->printer=100; // low paper
// ------------------ end of patch -------------------------------------------------
}
void hwapi::sys_getDynMachineConditions(uint8_t *leng, uint8_t *data) const
{
epi_restoreDynMachineConditions(leng, data);
}
void hwapi::sys_getDynMachineConditions(struct T_dynamicCondition *dynMachCond) const
{
uint16_t LL, nn;
char *start;
uint8_t buf[70], leng;
epi_restoreDynMachineConditions(&leng, buf);
// Puffer in struct eintragen:
LL=sizeof(struct T_dynamicCondition);
start = &dynMachCond->allDoorsDebounced;
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
}
uint32_t hwapi::cash_getAmountInVault(void) const
{
return epi_getCashBoxContent();
}
uint16_t hwapi::cash_getNrCoinsInVault(void) const
{
return epi_getNrOfCoinsInCashBox();
}
uint8_t hwapi::prn_getPrintResult() const
{
// return: 0: just printing, wait
// 1: OK - last print was succesful
// 2: error - not printed
struct T_dynamicCondition myDynMachCond;
sys_getDynMachineConditions(&myDynMachCond);
return myDynMachCond.resultOfLastTemplPrint;
// 0: unknown or printing in progress
// 1: OK, doc was printed 2: error, doc was not printed
}
uint8_t hwapi::prn_getCurrentPrinterState() const
{
// 0: printer OK
// bit0: near paper end bit1: no paper
// bit2: temperature error bit3: error head open
// bit4: paper jam in cutter
// bit6: no response bit7: serial rec. error
// bit5: printer not ready
uint8_t lastPrinterStatus;
uint8_t buf[70], leng;
if (!epi_areDcDataValid()) // was set to 0 with print command
return 0x40; // no response
// 2nd way to get dyn.conditions:
epi_restoreDynMachineConditions(&leng, buf);
lastPrinterStatus=buf[52];
return lastPrinterStatus;
// oder mit:
//struct T_dynamicCondition myDynMachCond;
//sys_getDynMachineConditions(&myDynMachCond);
//myDynMachCond.lastPrinterStatus
}
// 21.4.23TS: change function "sendDeviceSettings()" to use this struct: "struct T_devices"
void hwapi::sys_sendDeviceParameter(struct T_devices *deviceSettings) const
{
// same as "sendDeviceSettings()" but with much more data
uint8_t buf[64];
uint16_t LL, nn;
tslib_strclr(buf,0,64);
uint8_t *start;
// den gesamten struct in einen Puffer kopieren
LL=sizeof(struct T_devices);
start = &deviceSettings->kindOfPrinter;
nn=0;
do
{
buf[nn] = *start;
start++;
} while(++nn<LL);
longFDcmd_set(CMD2DC_DEVICE_PARAM,0,0,LL, buf);
}
void hwapi::sys_restoreDeviceParameter(struct T_devices *deviceSettings) const
{
// attention: only applies if function "sys_sendDeviceParameter()" was used to send this settings before
// cannot be used to see settings programmed by JsonFile
uint8_t buf[64];
uint8_t LL;
tslib_strclr(buf,0,64);
//runProcess->epi_restore64BdevParameter(&LL, buf); // wozu die???
epi_restoreRbDeviceSettings(&LL, buf); // viel besser, stimmt immer
Q_STATIC_ASSERT(sizeof(*deviceSettings) <= sizeof(buf));
memcpy(deviceSettings, buf, sizeof(*deviceSettings));
}
bool hwapi::sys_areDCdataValid(void) const
{
return epi_areDcDataValid();
}
bool hwapi::sys_sendingTest(void) const
{
/*
uint8_t buf[70], nn;
for (nn=0; nn<64; nn++) buf[nn]=nn+10;
if (check4freeFDstack()<16 )
{
qDebug()<< "hwapi_sys_test_sending: only: " << check4freeFDstack() << " free";
return false;
}
sendFDcmd_set(201, 202,1, 2,3,4,5);
sendFDcmd_set(203, 204,6, 7,8,9,5);
sendFDcmd_set(0, 205,1, 2,3,4,5);
longFDcmd_set (99, 0, 0, 64, buf); // long command must be <100!!!
sendFDcmd_set(0, 207,1, 6,7,8,9);
sendFDcmd_set(208, 209,1, 2,3,4,5);
sendFDcmd_set(210, 211,1, 6,7,8,9);
longFDcmd_set (98, 213,1, 64, buf);
sendFDcmd_set(214, 0,1, 2,3,4,5);
sendFDcmd_set(215, 0,1, 3,4,5,6);
sendFDcmd_set(216, 0,1, 2,3,4,5);
sendFDcmd_set(217, 0,1, 9,8,7,6);
sendFDcmd_set(218, 0,1, 2,3,4,5);
sendFDcmd_set(219, 0,1, 0,1,2,3);
sendFDcmd_set(220, 0,1, 2,3,4,5);
sendFDcmd_set(221, 222,1, 6,7,8,9);
*/
/*
for (nn=0; nn<16; nn++)
{
ll=checkNextFDcmd();
qDebug() << "sys_sendingTest reading: " << ll;
if (ll==2)
{
b_ret=longFDcmd_get(&nextWrCmd, &nextRdCmd, &blockNum, &length, data);
qDebug() << "long cmd: "<<nextWrCmd<<" "<<nextRdCmd<<" "<<blockNum<<" "<<length;
qDebug() << " / "<< data[0] << " / "<< data[1] << " / "<< data[2] << " / "<< data[3] << " / "<< data[4];
} else
if (ll==1)
{
b_ret=sendFDcmd_get(&nextWrCmd, &nextRdCmd, &blockNum, &dat1, &dat2, &dat3, &dat4);
qDebug() << "short cmd: "<<nextWrCmd<<" "<<nextRdCmd<<" "<<blockNum<<" "<<dat1<<" "<<dat2<<" "<<dat3<<" "<<dat4;
}
}
ll=checkNextFDcmd();
qDebug() << "completly read: " << ll;
*/
return true;
}
void hwapi::prn_requestCurrentDynData(void) const
{
sendFDcmd_set(0,39,0,0,0,0,0); // rd data dynData
epi_clearDynData();
}
bool hwapi::prn_getCurrentDynamicPrnValuesFromDC(uint8_t *dynPrnVal ) const
{
// which was sent to DC with: prn_sendDynamicPrnValues(uint8_t *dynPrnVal )
// retval true if data valid
bool isValid;
uint8_t buf[66];
isValid=epi_getDynPrnData(&buf[0]);
// bool epi_getDynPrnData(uint8_t *DCdynDat);
// buffer size: 64 byte
// return true if data are new and valid
if (isValid)
{
memcpy(dynPrnVal, buf, 64);
return true;
}
return false;
}
bool hwapi::prn_dynDataAreEqual(uint8_t *buf) const
{
for (int nn=0; nn<64; nn++)
if (lastSentDynData[nn]!=buf[nn])
return false;
return true;
}
bool hwapi::prn_printKombiticket(uint8_t nrOfKombi) const
// print four of the templates loaded by Json prior
// nr = 1..8
{
// return true if sending, false if cmd-stack is full
if ((nrOfKombi<1) || (nrOfKombi>8))
return false;
qCritical() << __PRETTY_FUNCTION__ << "RESET DC DATA VALID";
epi_clearDynMachineConditions(); // 24.6.23
gpi_storeDcDataValid(0);
return sendFDcmd_set(158, 0,0, nrOfKombi,0,0,0);
}
void hwapi::lock_triggerUpperSolenoid(void) const
{
sendFDcmd_set(159, 0,0, 0,0,0,0);
}
void hwapi::lock_triggerLowerSolenoid(void) const
{
sendFDcmd_set(160, 0,0, 0,0,0,0);
}
bool hwapi::doors_supervise(void) const
{
// no need to use
// will be called automatically
// new from 2023.06.12, generate some signals:
//virtual void hwapi_ doorServiceDoorOpened(void) const=0;
//virtual void hwapi_ doorVaultDoorOpened(void) const=0;
//virtual void hwapi_ doorCBinAndAllDoorsClosed(void) const=0;
//virtual void hwapi_ doorAllDoorsClosed(void) const=0;
//virtual void hwapi_ doorCoinBoxRemoved(void) const=0;
return runProcess->doors_supervise();
}
bool hwapi::dc_isAutoRequestOn(void) const
{
return gpi_isEmmisionOn();
}
uint16_t hwapi::log_getLatestAccountNumber(void) const
{
// new function 27.6.2023
// latest = highest, by now 8 records are stored in DC, prepare for 32
#define maxNrElements 8
uint8_t anz, nn;
uint16_t nummern[maxNrElements], highest=0;
memset(nummern, 0, sizeof(uint16_t)*maxNrElements);
log_getHoldAccountNumbers(&anz, nummern);
if (anz>maxNrElements) anz=maxNrElements;
for (nn=0; nn<anz; nn++)
if (nummern[nn]>highest)
highest=nummern[nn];
return highest;
}
uint8_t hwapi::log_getAvailableVaultBlocks(void) const
{
// return 0x0011 1111 if all 6 blocks arer loaded (one bit per block)
return epi_getLoadedVaultBlocks();
}
uint8_t hwapi::log_getAnswerToLastSlaveRequest(void) const
{
// use only for ONE request/command
// return: 0xFF: result unknown
// 0=OK
// 1= wrong length 2=wrong start sign 5= wrong crc
// 6= slave: master cmd was wrong 7: slave: could not write/read data
// 8=timeout, got no response from slave
return epi_getLastResult();
}
// use for important and extended commands (print more templates, print ticket...)
void hwapi::log_startSupervision(void) const
{
epi_startSupervision();
}
uint8_t hwapi::log_getAnswerToLastCmdBatch(void) const
{
// 0xFF: no command sent by now
// 0: started, in progress
// 1: done and OK
// 2: done and error
return epi_getBatchResult();
}
bool hwapi::log_getVaultData(uint8_t *data) const
{
// get vault record in linear 8bit buffer with 384 byte
uint16_t len=384;
uint8_t buf[400];
bool ret;
int nn;
ret=epi_restoreVaultRecord(&len, buf);
if (ret==false)
return false;
// 14.9.23 neu: Datensatz erst pruefen, [0..3] enthaelt "Psa>" und [4,5 =Abr.Nr]
uint16_t ds_acc_nr=uchar2uint(buf[5], buf[4]);
if (buf[0]=='P' && buf[1]=='S' && buf[2]=='A' && buf[3]=='>' && ds_acc_nr<60000)
{
// valid data, return data
for (nn=0; nn<384; nn++)
data[nn]= buf[nn];
return true;
} else
{
// wrong data, clear array
for (nn=0; nn<384; nn++)
data[nn]=0;
return false;
}
return false;
}
// new from 1.8.23
bool hwapi::prn_printOneAccountReceipt(uint16_t accountNr) const
{
qCritical() << __PRETTY_FUNCTION__ << "RESET DC DATA VALID";
// print one out of eight stored last accounting receipts
// function log_getHoldAccountNumbers() gives a list of acc-Nr. of the stored receipts
epi_clearDynMachineConditions(); // 24.6.23
gpi_storeDcDataValid(0);
uint8_t frei=check4freeFDstack();
if (frei<2)
return false;
uint8_t dat1, dat2;
dat1=uint2uchar(accountNr, LOWBYTE);
dat2=uint2uchar(accountNr, HIGHBYTE);
sendFDcmd_set(153, 0,0, dat1,dat2,0,0); // select this record
sendFDcmd_set(161, 0,0, 0,0,0,0); // print this
return true;
}
bool hwapi::prn_printAllAvailAccountReceipts(void) const
{
// same as: prn_printAccountReceipt() from line 1153
// return true if sending to DC OK, false if cmd-stack is full
return prn_printAccountReceipt();
}
uint16_t biox_crc_xmodem_update(uint16_t crc, uint8_t data)
{
// berechne CRC16 XModem nach Polynom x^16 + x^12 + x^5 + 1
int i;
crc = crc ^ ((uint16_t)data << 8);
for (i=0; i<8; i++)
{
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
return crc;
}
//bool hwapi::log_verifyVaultRecordByCrc(struct T_vaultRecord *retVR) const
bool hwapi::log_verifyVaultRecordByCrc(void) const
{
// return true if CRC16 is correct, data are 100% OK. Security level 1:65536
// verification is strongly recommended before further processing
// in case of "false"-result please reload from DC
uint16_t myChkSum=0, nn, myOldSum=0, recCheckSum=0;
uint16_t LL=332; //320; // in DC noch falsch, sollte 332 sein
uint8_t val;
uint8_t data[400];
memset(data,0,400);
log_getVaultData(data);
for (nn=0; nn<LL; nn++)
{
val=data[nn];
myChkSum=biox_crc_xmodem_update(myChkSum, val);
}
// Fehler im DC vom 27.7.23 Version 4.39: Berechnung nur bis 320
LL=320;
for (nn=0; nn<LL; nn++)
{
val=data[nn];
myOldSum=biox_crc_xmodem_update(myOldSum, val);
}
// nur bis DC4.40 noetig
// -------------------------------------------------------------
recCheckSum= uchar2uint(data[333], data[332]);
if (recCheckSum == myChkSum || recCheckSum == myOldSum)
return true;
return false;
}
uint16_t hwapi::log_DC_getNextAccountNumber(void) const
{
// the current cash box content will be backuped with this number on next cashbox-change
return epi_getNextDCaccNr();
}
void hwapi::log_DC_setNextAccountNumber(uint16_t newAccountingNumber) const
{
// the current cash box content will be backuped with this number on next cashbox-change
// use only in case of hardware replacements or errors which derailed the number
uint8_t LB, HB;
LB=uint2uchar(newAccountingNumber, LOWBYTE);
HB=uint2uchar(newAccountingNumber, HIGHBYTE);
sendFDcmd_set(162, 0,0, LB,HB,LB,HB);
}
void hwapi::log_DC_deleteAllVaultrecordsInDc(void) const
{
// use only in case of hardware replacements or errors which derailed the number
uint8_t sendData[10];
sendData[0]='D';
sendData[1]='e';
sendData[2]='l';
sendData[3]='e';
sendData[4]=0;
//longFDcmd_set(163, 0, 0, 8, sendData); // falsch!!! ( short Cmd, long data)
sendFDcmd_set(163, 0,0, sendData[0], sendData[1], sendData[2], sendData[3]);
}
void hwapi::log_DC_deleteAllTotalCounters(void) const
{
// use only in case of hardware replacements or errors which derailed the number
uint8_t sendData[10];
sendData[0]='D';
sendData[1]='e';
sendData[2]='l';
sendData[3]='e';
sendData[4]=0;
sendFDcmd_set(164, 0,0, sendData[0], sendData[1], sendData[2], sendData[3]);
}
void hwapi::dc_setNewCustomerNumber(uint16_t newCustNr) const
{
uint8_t LB, HB;
LB=uint2uchar(newCustNr, LOWBYTE);
HB=uint2uchar(newCustNr, HIGHBYTE);
sendFDcmd_set(165, 0,0, LB,HB,LB,HB);
}
void hwapi::dc_setNewMachineNumber(uint16_t newMachNr) const
{
uint8_t LB, HB;
LB=uint2uchar(newMachNr, LOWBYTE);
HB=uint2uchar(newMachNr, HIGHBYTE);
sendFDcmd_set(166, 0,0, LB,HB,LB,HB);
}
void hwapi::dc_setNewBorough(uint16_t newBorough) const
{
uint8_t LB, HB;
LB=uint2uchar(newBorough, LOWBYTE);
HB=uint2uchar(newBorough, HIGHBYTE);
sendFDcmd_set(167, 0,0, LB,HB,LB,HB);
}
void hwapi::dc_setNewZone(uint16_t newZone) const
{
uint8_t LB, HB;
LB=uint2uchar(newZone, LOWBYTE);
HB=uint2uchar(newZone, HIGHBYTE);
sendFDcmd_set(168, 0,0, LB,HB,LB,HB);
}
// ----------------------- new functions from 8.9.23 --------------------------------------
// new mifare functions
// call void hwapi::request_MifareID() before! (cmd24)
// send 24
/* further mifare requests:
void hwapi::request_MifareReaderState() const; // 24
void hwapi::request_MifareCardType() const; // 109
void hwapi::request_MifareAtbType() const; // 25
void hwapi::request_MifareData(uint8_t dataBlockNumber);
// dataBlockNumber=0...11 send cmd 28
*/
QString hwapi::mif_getReaderType(void) const
{
// new, 8.9.23, return reader type and version like "SL025-1.8"
QString myStr;
uint8_t mifData[66];
char myChr;
epi_restoreMifHwData(mifData, 66);
/* stand 8.9.23
struct T_Mifare
{
UCHAR ReaderState; // 1: OK 0: not OK
UCHAR res1;
2: UCHAR ReaderVersion[10];
12: UCHAR CardPresent;
UCHAR CardSelected;
UCHAR Cardtype;
UCHAR CardAllowed; // 0,1 nur Mifare Classic 1k und 4k zugelassen
UCHAR CardSize; // 1 or 4 (kB)
UCHAR LengOfUid; // 4 or 7 (byte)
18: UCHAR UID[8]; // 4 byte oder 7 byte, Format binär
// 26 byte bis hier
UCHAR res2;
UCHAR res3;
28: ULONG UidH; // bei 4byte Uid alles 0
ULONG UidL;
36: UCHAR SectorLogged; // result of loggin: 2=success 3=failed 1=no_tag 8=addr overflow F0=wrongCmd
UCHAR CurrentSector;
UCHAR RD_WR_Result;
UCHAR res4;
// 40byte lang
};
*/
myStr.clear();
// UID in buf[18...25]
for (int ii=0;ii<10; ii++)
{
myChr=(char)mifData[ii+2];
//myStr.append(QString::number()); geht nicht, anzeige als Zahl
myStr.append(myChr);
}
return myStr;
}
// mif_getCardType gibts oben schon!
void hwapi::mif_getCardSize(uint8_t *cardSize, uint8_t *idLeng) const
{
// new, 8.9.23
// cardSize=1k or 4kByte (Mifare Classic)
// idLeng =4Byte or 7 byte
uint8_t mifData[66];
epi_restoreMifHwData(mifData, 66);
*cardSize=mifData[16];
*idLeng=mifData[17];
}
// neu 14.9.23
char hwapi::mif_getAtbCardData(uint8_t *buf, uint8_t maxBuffSiz) const
{
// return complete buffer binary, just for test purpose
uint8_t mifData[66], nn;
if (maxBuffSiz>=64)
{
epi_restoreMifAtbData(mifData, 66);
for (nn=0; nn<64; nn++)
buf[nn]=mifData[nn];
return true;
}
return false;
}
bool hwapi::mif_isValidAtbCard(void) const
{
uint8_t receivedData[66], nn;
//uint32_t mifatb_cunu, mifatb_cardnu, mifatb_creditAmount, mifatb_creditTime;
//QString mifatb_cardTyp, mifatb_lpr, mifatb_group, mifatb_zone;
//uint8_t mifatb_times[10];
uint8_t lprbuff[20];
bool ret;
epi_restoreMifAtbData(receivedData, 66);
for (nn=0; nn<16; nn++)
{
lprbuff[nn]=char(receivedData[12+nn]);
//mifatb_lpr.append(char(receivedData[12+nn])); // "AtbPsa1256Ptu5_!" = recognition ATB card
}
/*
//mifatb_lpr.clear();
mifatb_cunu=uchar2ulong(receivedData[3], receivedData[2],receivedData[1],receivedData[0]);
// 281
mifatb_cardnu=uchar2ulong(receivedData[7], receivedData[6],receivedData[5],receivedData[4]);
// always 0, not used
mifatb_cardTyp.clear();
for (nn=0; nn<4; nn++)
mifatb_cardTyp.append(char(receivedData[8+nn])); // = "PREP" no idea what that means
mifatb_group.clear();
for (nn=0; nn<8; nn++)
mifatb_group.append(char(receivedData[28+nn])); // "7x§0 TPf" used for card type
mifatb_zone.clear();
for (nn=0; nn<8; nn++)
mifatb_zone.append(char(receivedData[36+nn])); // "PNsax001" used for personal number and shortcode
for (nn=0; nn<10; nn++)
mifatb_times[nn]=receivedData[44+nn];
// 0..9: (Start) day, month, year, hh, min (Stop) day, month, year, hh, min,
mifatb_creditAmount= uchar2ulong(receivedData[57], receivedData[56],receivedData[55],receivedData[54]);
// is used as expire date/time
mifatb_creditTime = uchar2ulong(receivedData[61], receivedData[60],receivedData[59],receivedData[58]);
// always 0
// qDebug()<<"got MifAtbData: "<<mifatb_cunu<<" "<< mifatb_cardnu<<" "<< mifatb_cardTyp<<" "<< mifatb_lpr
// <<" "<< mifatb_group<<" "<< mifatb_zone<<" "<< mifatb_times[0]<<" "<< mifatb_times[1]<<" "<< mifatb_times[2]
// <<" "<< mifatb_times[3]<<" "<< mifatb_times[4]<<" "<< mifatb_times[5]<<" "<< mifatb_times[6]
// <<" "<< mifatb_times[7]<<" "<< mifatb_times[8]<<" "<< mifatb_times[9]
// <<" "<< mifatb_creditAmount<<" "<< mifatb_creditTime;
*/
//ret=tslib_strComp(&lprbuff[0], "AtbPsa1256Ptu5_!"); // bringt Warnung, unloesbar.
ret=false;
if (lprbuff[0]=='A' && lprbuff[1]=='t' && lprbuff[2]=='b' && lprbuff[3]=='P' && lprbuff[4]=='s' &&
lprbuff[5]=='a' && lprbuff[6]=='1' && lprbuff[7]=='2' && lprbuff[8]=='5' && lprbuff[9]=='6' &&
lprbuff[10]=='P' && lprbuff[11]=='t' && lprbuff[12]=='u' && lprbuff[13]=='_' && lprbuff[14]=='!' )
ret=1;
//qDebug()<<"hwapi::mif_isValidAtbCard: "<<ret;
return ret;
}
uint32_t hwapi::mif_getAtbCardCuNu(void) const
{
uint8_t receivedData[66];
epi_restoreMifAtbData(receivedData, 66);
return uchar2ulong(receivedData[3], receivedData[2],receivedData[1],receivedData[0]);
}
uint8_t hwapi::mif_getAtbCardTyp(void) const
{
// return 1=upper door card 1=lower door 3=printer-test 4=coin-test
// 0: not a valid atb2020 card
uint8_t receivedData[66];
uint8_t mifatb_group[8], nn;
epi_restoreMifAtbData(receivedData, 66);
//mifatb_group.clear();
for (nn=0; nn<8; nn++)
mifatb_group[nn]=receivedData[28+nn]; // "7x§0 TPf" used for card type
if (mifatb_group[0]=='7' && mifatb_group[1]=='x' && mifatb_group[3]=='0' && mifatb_group[4]==' ' ) // && mifatb_group[2]=='§' geht nicht
{
// card type is valid
if (mifatb_group[5]=='D' && mifatb_group[6]=='U')
return 1;
if (mifatb_group[5]=='D' && mifatb_group[6]=='V')
return 2;
if (mifatb_group[5]=='T' && mifatb_group[6]=='P')
return 3;
if (mifatb_group[5]=='T' && mifatb_group[6]=='C')
return 4;
}
return 0;
}
QString hwapi::mif_getAtbCardPerso(void) const
{
uint8_t receivedData[66], nn;
QString mifatb_zone;
epi_restoreMifAtbData(receivedData, 66);
mifatb_zone.clear();
for (nn=0; nn<8; nn++)
mifatb_zone.append(char(receivedData[36+nn])); // "PNsax001" used for personal number and shortcode
return mifatb_zone;
}
void hwapi::mif_getAtbCardExpire(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute) const
{
uint8_t receivedData[66], nn, mifatb_times[10];
epi_restoreMifAtbData(receivedData, 66);
for (nn=0; nn<10; nn++)
mifatb_times[nn]=receivedData[44+nn];
// 0..9: (Start) day, month, year, hh, min (Stop) day, month, year, hh, min,
// qDebug()<<"hwapi::mif_getAtbCardExpire: "<< mifatb_times[0] << " " << mifatb_times[1] << " "
// << mifatb_times[2] << " " << mifatb_times[3] << " " << mifatb_times[4];
// for the 2020 cards the field "mifatb_creditAmount" is used as expire date/time:
//for (nn=0; nn<5; nn++)
// mifatb_times[nn]=receivedData[54+nn]; falsch
uint32_t ultmp= uchar2ulong(receivedData[57], receivedData[56],receivedData[55],receivedData[54]); // =mifatb_creditAmount
mifatb_times[4]=ultmp%100;
ultmp/=100;
mifatb_times[3]=ultmp%100;
ultmp/=100;
mifatb_times[2]=ultmp%100;
ultmp/=100;
mifatb_times[1]=ultmp%100;
ultmp/=100;
mifatb_times[0]=ultmp%100;
*year = mifatb_times[0];
*month = mifatb_times[1];
*day = mifatb_times[2];
*hour = mifatb_times[3];
*minute = mifatb_times[4];
}
// ------------------------------------------------------------------------------------
// Device-Controller-Bootloader convenient version 21.09.2023
// ------------------------------------------------------------------------------------
// use this to jump to BL:
//void hwapi::bl_rebootDC(void) const
// use this to start BL:
// void hwapi::bl_startBL(void) const
// call this in order to get response from BL:
//void hwapi::bl_checkBL(void) const
// evaluate BL response:
//bool hwapi::bl_isUp(void) const
// 29.9.23: new: "completeStart" function, replaces bl_rebootDC(), bl_startBL() and bl_checkBL()
// result can be verified with bl_isUp() as before
bool hwapi::bl_completeStart(void) const
{
// must be used in DC's normal operation
runProcess->bl_completeStart();
//hwapi_triggerBL->start(100);
return true;
}
// select binfile-name in GUI
// send binfile-name to BL-processor:
bool hwapi::bl_storeFirmware(QString fileName) const
{
// load binary file 3x and compare
// return true if loaded correctly
// return false: error, could not load correctly
return dcBL_loadBinSafe(fileName);
}
// request the number of blocks for this file
uint16_t hwapi::bl_getNrOfFirmwareBlocks(void) const
{
// size of the loaded bin file in 64byte blocks
// call after bl_storeFirmware()
return dcBL_getNrOfBlocks();
}
// call this function with "blockNumber"=0,1,2,3.....bl_getNrOfFirmwareBlocks
//the last block "bl_getNrOfFirmwareBlocks()" is sent as conclusion command (important!)
bool hwapi::bl_blockAutoLoad(uint16_t blockNumber) const
{
// call in loop from block number 0 up to <= "dcBL_getNrOfBlocks()"
// but after every call WAIT (!) for response "bl_blockAutoResponse()" !!!!
// data will be sent to DC, if neccesary addr will be sent additionally
// if neccesary sending will automatically repeat up to 3times
// retval: false if blockNumber>4095, true else
return dcBL_sendOneBlockCpl(blockNumber);
}
// check out this response after every block-sending, wait until >0!!!
int8_t hwapi::bl_blockAutoResponse(void) const
{
// after every "bl_blockAutoLoad()" call this until response
// retval 0: wait 1: OK, blk was sent 2: OK, transfer complete
// 3: error despite repeating, cancel. probably bin file corrupted
// Max duration: 3x no response from BL = 900ms
return dcBL_getBlockResult();
}
// finally call:
// void hwapi::bl_stopBL(void) const
// -------------- end of bootloader ---------------------------------------------------
// new from 28.9.23 and earliest from DC version 4.45
// get all versions of the DC-Jsons
void hwapi::sys_requestJsonVersions(uint8_t jsonNr) const
{
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 5=printer template 1 ..... 36= template 32
sendFDcmd_set(0, 21, jsonNr,0,0,0,0);
}
void hwapi::sys_getJsonVersions(uint8_t jsonNr, char *versionString) const
{
epi_getJsonVersion(jsonNr, versionString);
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 5=printer template 1 ..... 36= template 32
// length of buffer is always 16 byte
}
// ------------------------------------------------------------------------------------
// Coin Changer
// ------------------------------------------------------------------------------------
void hwapi::changer_returnCoins(uint32_t amountInCent) const
{
// command to give change
uint8_t buff[8];
buff[0]=ulong2uchar(amountInCent, 0); //LOWBYTE
buff[1]=ulong2uchar(amountInCent, 1);
//buff[2]=ulong2uchar(amountInCent, 2);
//buff[3]=ulong2uchar(amountInCent, 3); // HIGHBYTE
// repeat for security:
buff[2]=ulong2uchar(amountInCent, 0); //LOWBYTE
buff[3]=ulong2uchar(amountInCent, 1);
//buff[6]=ulong2uchar(amountInCent, 2);
//buff[7]=ulong2uchar(amountInCent, 3); // HIGHBYTE
// longFDcmd_set(169, 0,0, 4,buff); // short cmd max 4 byte!
sendFDcmd_set(169,0,0,buff[0], buff[1], buff[2], buff[3]);
}
void hwapi::changer_requestChangeResult(void) const
{
sendFDcmd_set(0, 115,0, 0,0,0,0);
}
uint8_t hwapi::changer_getChangeResult(uint32_t *returnedAmount) const
{
return epi_getChangerResult(returnedAmount);
// get result of coin dispensing
// receivedData[0]: 0: not yet started 1:amount returned
// 2:only partial return 3: no return possible
// receivedData[2,3,4,5]: returned amount
}
void hwapi::changer_getAllParameters(struct T_changer *mw) const
{
// requested automatically with 23, same like EMP
uint8_t leng, data[66], pp, nn;
epi_restoreEmpSettings(&leng, data); // expected length = 64 byte
// get 64 bytes about Changer (mw), see interfaces.h-file
mw->setup = data[0];
mw->state = data[1];
mw->level = data[2];
mw->countryCode = uchar2uint(data[4], data[3]);
mw->scale = data[5];
mw->decimals= data[6];
for (nn=0; nn<16; nn++)
mw->coinSetup[nn]= data[nn+7]; // 7...22
mw->intendedAcceptance = uchar2uint(data[24], data[23]);
mw->tokenChannel= data[25];
mw->pollingRunning= data[26];
mw->paymentRunning= data[27];
pp=28;
for (nn=0; nn<16; nn++)
{
mw->denomination[nn] = uchar2uint(data[pp+1], data[pp]);
pp+=2;
}
// bis pp=60
mw->availableTubes = uchar2uint(data[61], data[60]);
}
void hwapi::changer_requestTubelevel(void) const
{
sendFDcmd_set(0, 40,0, 0,0,0,0);
}
void hwapi::changer_getTubelevel(struct T_chg_Tub *tubLevel) const
{
// don't use tubeDispens[], it's not yet correct!
uint16_t LL, nn;
uint8_t *start;
uint8_t buf[66];
epi_restoreTubeLevel(buf);
// Puffer in struct eintragen:
LL=sizeof(struct T_chg_Tub);
start = &(tubLevel->tubeLevel[0]);
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
}
// ------------------------------------------------------------------------------------
// bank note acceptor
// ------------------------------------------------------------------------------------
void hwapi::bna_sendSettings(uint16_t notesToAccept, uint16_t parameters,
uint16_t *billDenomination,
uint32_t acceptanceLimit) const
{
// notesToAccept: bit0=bill1 (lowest donomination) bitH=accept bit L = deny
// parameters: e.g. use escrow function for some notes
// billDenomination = array of 16 bill values (e.g. 5, 10, 20...)
// these can be set alternatively by Json-File DC2C_cash.json
// acceptanceLimit: device will stop acceptance once this amount is reached and
// optionally keep last bill in escrow until vend_success()
// is called (put bill to stacker) or vend_failed() is called (return bill)
uint16_t noteAcc=notesToAccept;
uint16_t para=parameters;
uint16_t denom[16];
uint32_t limit=acceptanceLimit;
uint8_t buf[64], nn, pp;
for (nn=0; nn<16; nn++)
denom[nn]=billDenomination[nn];
buf[0]=uint2uchar(noteAcc, LOWBYTE);
buf[1]=uint2uchar(noteAcc, HIGHBYTE);
buf[2]=uint2uchar(para, LOWBYTE);
buf[3]=uint2uchar(para, HIGHBYTE);
pp=4;
for (nn=0; nn<16; nn++)
{
buf[pp++]=uint2uchar(denom[nn], LOWBYTE);
buf[pp++]=uint2uchar(denom[nn], HIGHBYTE);
}
buf[pp++]=ulong2uchar(limit, 0);
buf[pp++]=ulong2uchar(limit, 1);
buf[pp++]=ulong2uchar(limit, 2);
buf[pp++]=ulong2uchar(limit, 3);
longFDcmd_set(35, 41, 0, pp, buf);
}
void hwapi::bna_setCurrentAcceptance(uint16_t notesToAccept) const
{
// can be used to block notes dynamically, example: from now only 5€ bills are allowed (if only 3€ are to be paid)
uint8_t LB, HB;
uint16_t val=notesToAccept;
LB=uint2uchar(val, LOWBYTE);
HB=uint2uchar(val, HIGHBYTE);
sendFDcmd_set(170, 0, 0, LB, HB, LB, HB);
}
void hwapi::bna_requestParameters(void) const
{
// send command to DC in order to get static invariable device parameters like currency
// device must be powered and polled to get these
sendFDcmd_set(0, 41, 0, 0, 0, 0, 0);
}
bool hwapi::bna_getAllParameters(struct T_bna *bna) const
{
// get all constant data from reader (e.g. currency)
// and actual Host-Settings (sent with bna_sendSettings() or json)
// retval = true if data are valid
uint8_t buf[66], nn, pp;
epi_restoreBnaParams(buf);
bna->setup=buf[0];
bna->FeatureLevel=buf[1];
bna->countryCode=uchar2uint(buf[3], buf[2]);
bna->scalingFactor=uchar2uint(buf[5], buf[4]);
bna->decimalPlace=buf[6];
bna->pad1=0;
bna->stackerCap=uchar2uint(buf[8], buf[7]);
bna->billSecureLevel=uchar2uint(buf[10], buf[9]);
bna->hasEscrow=buf[11];
for (nn=0; nn<16; nn++)
bna->accBillTypes[nn] = buf[nn+12];
bna->currentStackerLevel = uchar2uint(buf[29], buf[28]);
bna->intendedAccept = uchar2uint(buf[31], buf[30]);
bna->pad2=0;
pp=32;
for (nn=0; nn<16; nn++)
{
bna->billDenomination[nn] = uchar2uint(buf[pp+1], buf[pp]);
pp+=2;
}
if (bna->setup)
return true;
else
return false;
}
void hwapi::bna_requestCurrentNotes(void) const
{
// send command to DC in order to get transaction data
sendFDcmd_set(0, 116, 0, 0, 0, 0, 0);
}
uint8_t hwapi::bna_getCurrentNotes(uint16_t latestBill, uint16_t *currentNotes) const
{
// returns number of collected bank notes since start-command (current transaction)
// latestBill: not used
// currentNotes[0] = last bill value
// currentNotes[1] = 0/1 1 if bill in escrow 0 if bill in cash box (stacker)
// currentNotes[2,3] = total sum of collected bills within this transaction
// incoming data:
//DB1: nr of bills (this transaction)
//DB2: 1 if bill in escrow
//DB3..6: collected amount
//DB7,8: denomination of last bill
uint8_t buf[10], haveBilInEscrow, haveNrOfBills;
uint16_t lastBillVal;
uint32_t collAmountThisTrans;
epi_restoreBnaCollection(buf);
haveNrOfBills=buf[0];
haveBilInEscrow=buf[1];
collAmountThisTrans = uchar2ulong(buf[5],buf[4],buf[3],buf[2]);
lastBillVal = uchar2uint(buf[7],buf[6]);
currentNotes[0]=latestBill; // just to get rid of compiler warning
currentNotes[0]=lastBillVal;
currentNotes[1]=haveBilInEscrow;
currentNotes[2]=uint16_t(collAmountThisTrans);
collAmountThisTrans>>=16;
currentNotes[3]=uint16_t(collAmountThisTrans);
return haveNrOfBills;
}
void hwapi::bna_requestStackerLevel(void) const
{
sendFDcmd_set(0, 42, 0, 0, 0, 0, 0);
}
uint16_t hwapi::bna_getStackerLevel(uint32_t *amountInStacker, uint16_t *countOfBills) const
{
// return val: nr of bills in stacker
// countOfBills[0..7] = count of bills of bill-type 0..7 (e.g. countOfBills[0]=nr of 5€-bills in stacker)
// countOfBills[8..15] = value of bill-type 0...7
// receive data:
//je zwei Byte pro Wert,
//1…16: Anzahl Scheine pro Typ
//33…48: Wertigkeit der Typen
uint8_t buf[66], nn, pp, qq;
uint16_t nrOfBills[16], valueOfBills[16], anzahl=0;
uint32_t totalSum=0;
epi_restoreBnaContent(buf);
pp=0; qq=32;
for (nn=0; nn<16; nn++)
{
nrOfBills[nn]=uchar2uint(buf[pp+1],buf[pp]);
pp+=2;
valueOfBills[nn]=uchar2uint(buf[qq+1],buf[qq]);
qq+=2;
}
//qDebug()<< "CAmaster hwapi::bna_getStackerLevel " << nrOfBills[0] <<" "<< nrOfBills[1]
// <<" "<<nrOfBills[2]<<" "<<nrOfBills[3];
// qDebug()<< valueOfBills[0] <<" "<< valueOfBills[1] <<" "<<valueOfBills[2]<<" "<<valueOfBills[3];
// nur 8 zurueckmelden, mehr kommen derzeit von DC auch nicht
for (nn=0; nn<8; nn++)
{
countOfBills[nn]=nrOfBills[nn];
countOfBills[nn+7]=valueOfBills[nn];
}
for (nn=0; nn<8; nn++)
{
totalSum += nrOfBills[nn] * valueOfBills[nn];
anzahl += nrOfBills[nn];
}
//qDebug()<<"sum: "<< totalSum <<" Anzahl: "<<anzahl;
*amountInStacker=totalSum;
return anzahl;
}
QObject const *hwapi::getAPI() {
return this;
}
bool hwapi::dcDownloadRequest(QString const &dcFileToDownload) const {
SharedMem *data = SharedMem::getData();
if (!data) {
return false;
}
char *fNameBuffer = data->m_downLoadDC.m_filename[(int)SharedMem::DCDownload::FILE_INDEX::DC_BINARY];
size_t const size = sizeof(data->m_downLoadDC.m_filename);
std::memset(fNameBuffer, 0x00, size);
std::memcpy(fNameBuffer, dcFileToDownload.toStdString().c_str(),
std::min(size, strlen(fNameBuffer)-1));
data->m_downLoadDC.m_totalBlocks = 0;
data->m_downLoadDC.m_currentblockNumber = 0;
data->m_downLoadDC.m_requested = true;
data->m_downLoadDC.m_running = false; // download thread is not running
data->m_downLoadDC.m_finished = true;
return true;
}
bool hwapi::dcDownloadRequested() const {
SharedMem const *data = SharedMem::getData();
// should be false at entry
return data ? data->m_downLoadDC.m_requested.load() : false;
}
bool hwapi::dcDownloadResetRequest() const {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_requested = false;
}
return true;
}
bool hwapi::dcDownloadRequestAck() const {
SharedMem *data = SharedMem::getData();
if (data) {
if (data->m_downLoadDC.m_requested) {
data->m_downLoadDC.m_requested = false;
data->m_downLoadDC.m_running = true;
data->m_downLoadDC.m_finished = false;
}
}
return false;
}
bool hwapi::dcDownloadRunning() const {
SharedMem const *data = SharedMem::getDataConst();
if (data) {
int cnt = 10;
while (--cnt > 0) {
bool running = data->m_downLoadDC.m_running.load();
bool finished = data->m_downLoadDC.m_finished.load();
if (!running || finished) {
if (cnt < 3) {
qCritical() << "DOWNLOAD THREAD NOT RUNNING" << running << finished;
}
QThread::msleep(500);
} else break;
}
// qCritical() << "DOWNLOAD RUNNING" << cnt << (cnt > 0);
return (cnt > 0);
}
return false;
}
void hwapi::dcDownloadThreadFinalize(DownloadThread *dthread) {
delete dthread;
m_downloadThread = nullptr;
}
bool hwapi::dcDownloadFinished() {
SharedMem const *data = SharedMem::getDataConst();
if (data) {
int cnt = 10;
while ((--cnt > 0) &&
((data->m_downLoadDC.m_running.load() == true) &&
(data->m_downLoadDC.m_finished.load() == false))) {
QThread::sleep(1);
}
//if (cnt > 0) {
// delete m_downloadThread;
// m_downloadThread = nullptr;
// return true;
//}
}
return false;
}
// download thread
bool hwapi::dcDownloadThreadStart() {
m_downloadThread = new DownloadThread(this);
if (m_downloadThread) {
m_downloadThread->start();
int cnt = 10;
while (--cnt > 0 && !dcDownloadThreadRunning()) {
QThread::msleep(200);
}
return (cnt > 0);
}
return false;
}
bool hwapi::dcDownloadThreadRunning() const {
return (dcDownloadGetRunning() == true)
&& (dcDownloadGetFinished() == false);
}
bool hwapi::dcDownloadThreadFinished() const {
return (dcDownloadThreadRunning() == false);
}
// report thread
bool hwapi::dcDownloadReportThreadStart() { // only start reporting thread
int cnt = 10; // if download thread is running
while (--cnt > 0 && !dcDownloadRunning()) {
QThread::msleep(500);
}
if (cnt > 0) {
m_reportingThread = new ReportingThread(this);
if (m_reportingThread) {
m_reportingThread->start();
cnt = 10;
while (--cnt > 0 && !dcDownloadReportThreadRunning()) {
QThread::msleep(200);
}
return (cnt > 0);
}
}
return false;
}
bool hwapi::dcDownloadReportThreadRunning() const {
return m_reportingThread ? m_reportingThread->isRunning() : false;
}
void hwapi::dcDownloadReportThreadFinalize() {
if (m_reportingThread) {
if (m_reportingThread->isFinished()) {
delete m_reportingThread;
m_reportingThread = nullptr;
}
}
}
void hwapi::dcDownloadReportThreadQuit() {
if (m_reportingThread) {
m_reportingThread->quit();
}
}
bool hwapi::dcDownloadReportThreadFinished() const {
return m_reportingThread ? m_reportingThread->isFinished() : false;
}
bool hwapi::dcDownloadReportStart() const {
int cnt = 10;
while (--cnt > 0 && !dcDownloadRunning()) {
QThread::msleep(200);
}
return (cnt == 0);
}
bool hwapi::dcDownloadReportRunning() const {
return dcDownloadReportThreadRunning();
}
bool hwapi::dcDownloadReportFinished() {
int cnt = 10;
while (--cnt > 0 && !dcDownloadReportThreadFinished()) {
QThread::sleep(1);
}
if (cnt == 0 && !dcDownloadReportThreadFinished()) {
return false;
}
if (dcDownloadReportThreadFinished()) {
delete m_reportingThread;
m_reportingThread = nullptr;
}
return true;
}
QString hwapi::dcDownloadFileName() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_filename[(int)SharedMem::DCDownload::FILE_INDEX::DC_BINARY] : "";
}
bool hwapi::dcDownloadSetRequested(bool requested) {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_requested = requested;
return true;
}
return false;
}
bool hwapi::dcDownloadSetRunning(bool running) {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_running = running;
return true;
}
return false;
}
bool hwapi::dcDownloadSetFinished(bool finished) {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_finished = finished;
return true;
}
return false;
}
void hwapi::dcDownloadSetTotalBlockNumber(uint16_t totalBlockNumber) {
SharedMem::getData()->m_downLoadDC.m_totalBlocks = totalBlockNumber;
}
void hwapi::dcDownloadSetCurrentBlockNumber(uint16_t currentBlockNumber) {
SharedMem::getData()->m_downLoadDC.m_currentblockNumber = currentBlockNumber;
}
uint16_t hwapi::dcDownloadGetTotalBlockNumber() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_totalBlocks.load() : 0;
}
uint16_t hwapi::dcDownloadGetCurrentBlockNumber() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_currentblockNumber.load() : 0;
}
bool hwapi::dcDownloadGetRequested() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_requested.load() : 0;
}
bool hwapi::dcDownloadGetRunning() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_running.load() : 0;
}
bool hwapi::dcDownloadGetFinished() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_running.load() : 0;
}