ATBUpdateTool/DCPlugin/src/hwapi.cpp

4065 lines
106 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
*
*/
#include <stdint.h>
#include <unistd.h>
#include <thread>
#include <algorithm>
#include <QFileInfo>
#include "tslib.h"
#include "hwapi.h"
#include "sendWRcmd.h"
#include "controlBus.h"
#include "storeINdata.h"
#include "dcBL.h"
#include "shared_mem_buffer.h"
#include <QDebug>
#include <QSharedMemory>
#include "interfaces.h"
static uint32_t hwapi_lastStartAmount;
static const QMap<QString, int> baudrateMap = {
{"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3},
{"57600" , 4}, {"115200" , 5}
};
hwapi::hwapi(QObject *parent) : QObject(parent) {
// create or attach shared memory segment
// !!! The compoment creating the shared memory MUST be ATBQT !!!
m_sharedMem = SharedMemBuffer::getShm(sizeof(SharedMemBuffer));
if (m_sharedMem) {
if (m_sharedMem->isAttached()) {
qInfo() << "Shared memory ("
<< sizeof(SharedMemBuffer) << "bytes) created and attached";
}
} else {
qCritical() << "Creating/attaching shared memory failed";
}
sendWRcmd_INI();
myDatif = new T_datif();
connect(myDatif, SIGNAL(datif_templatePrintFinished_OK()), this, SLOT(hwapi_slotPrintFinished_OK()));
connect(myDatif, SIGNAL(datif_templatePrintFinished_Err()), this, SLOT(hwapi_slotPrintFinished_Err()));
connect(myDatif, SIGNAL(datif_gotNewCoin()), this, SLOT(hwapi_slotGotCoin()));
}
hwapi::~hwapi() {
if (m_sharedMem && m_sharedMem->isAttached()) {
m_sharedMem->detach();
}
}
void hwapi::hwapi_slotPrintFinished_OK(void) {
emit hwapi_templatePrintFinished_OK();
}
void hwapi::hwapi_slotPrintFinished_Err(void) {
emit hwapi_templatePrintFinished_Err();
}
void hwapi::hwapi_slotGotCoin(void) {
// new coin was inserted while transaction and new amount reported:
emit hwapi_gotNewCoin();
uint32_t newSum=epi_CurrentPaymentGetAmount();
if (newSum>=hwapi_lastStartAmount)
emit hwapi_vendStopByMax();
}
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);
}
// ------------------------------------------------------------------------------
// Level 0 commands, interface
// open, close, change serial interface
// actually not neccessary as it is opened automatically on program start
// start automatic READ requests
// ------------------------------------------------------------------------------
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
//qDebug() << "~~>LIB" << "dc_openSerial called... " ;
epi_setSerial(BaudNr, BaudStr, ComName, connect);
// Actions: open serial port with parameters
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (dc_isPortOpen()) {
return true;
}
}
return false;
}
QStringList hwapi::dc_getStatus() const {
QStringList status;
if (m_sharedMem) {
SharedMemBuffer const *shMem = SharedMemBuffer::getDataConst();
status += QString("comport : %1").arg(shMem->rs.comportName);
status += QString("baudrate : %1").arg(shMem->rs.baudNr);
status += QString("baudNr : %1").arg(shMem->rs.baudStr);
status += QString("connect : %1").arg(shMem->rs.connect);
status += QString("port open: %1").arg(shMem->rs.portIsOpen);
// to be continued
}
return status;
}
bool hwapi::dc_closeSerial(void) const {
epi_closeSerial();
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (!dc_isPortOpen()) {
return true;
}
}
return false;
}
bool hwapi::dc_isPortOpen(void) const {
if (myDatif) {
T_prot* prot = myDatif->getProt();
if (prot) {
T_com *com = prot->getSerialPort();
if (com) {
return com->isPortOpen();
}
}
}
return false;
//return epi_isSerialPortOpen();
}
void hwapi::dc_autoRequest(bool on) const
{
// automatically request ALL digital and analog sensors, get time/date, get status information
if (on)
epi_startEmmision(1);
else
epi_startEmmision(0);
}
/******************************************************************************/
//
// LEVEL 2: Help-functions for hwapi::dc_updateDC.
//
/******************************************************************************/
hwapi::DownloadResult hwapi::sendStatus(int ret) const {
switch (ret) { // return values of dc are:
case 0: // 0: no answer by now
return DownloadResult::NOP; // 1: error
case 10: // 10: success
return DownloadResult::OK;
default:;
}
return DownloadResult::ERROR;
}
hwapi::DownloadResult hwapi::sendNextAddress(int bNum) const {
// sends address only if blockNumber is one of 0, 1024, 2048, 3072, 4096
int noAnswerCount = 0;
int errorCount = 0;
if ( bNum==0 || bNum==1024 || bNum==2048 || bNum==3072 || bNum==4096 ) {
qDebug() << "addr-block" << bNum << "...";
while (noAnswerCount <= 250) {
bl_sendAddress(bNum);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
DownloadResult const res = sendStatus(bl_wasSendingAddOK());
if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) {
if (++errorCount >= 10) {
qCritical() << "addr-block" << bNum << "...FAILED";
return res;
}
} else { // res == DownloadResult::OK
qInfo() << "addr-block" << bNum << "...OK";
return res;
}
} else {
noAnswerCount += 1; // no answer by now
}
}
// wait max. about 3 seconds
return DownloadResult::TIMEOUT;
}
// blockNumber is not one of 0, 1024, 2048, 3072, 4096 -> do nothing
return DownloadResult::NOP;
}
hwinf::DownloadResult hwapi::sendNextDataBlock(QByteArray const &binary,
int bNum) const {
uint8_t local[66];
int const bAddr = bNum * 64;
int noAnswerCount = 0;
int errorCount = 0;
memcpy(local, binary.constData() + bAddr, 64);
local[64] = local[65] = 0x00;
qDebug() << "data for addr" << bAddr << "...";
while (noAnswerCount <= 250) {
bl_sendDataBlock(64, local);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
DownloadResult const res = sendStatus(bl_wasSendingDataOK());
if (res != DownloadResult::NOP) {
if (res == DownloadResult::ERROR) {
if (++errorCount >= 10) {
qCritical() << "data for addr" << bAddr << "...FAILED";
return res;
}
} else {
qInfo() << "data for addr" << bAddr << "...OK";
return res;
}
} else {
noAnswerCount += 1; // no answer by now
}
}
// wait max. about 3 seconds
return DownloadResult::TIMEOUT;
}
hwinf::DownloadResult hwapi::dc_downloadBinary(QByteArray const &b) const {
int const nBlocks = (((b.size())%64)==0) ? (b.size()/64) : (b.size()/64)+1;
qInfo() << "total number of bytes to send to dc" << b.size();
qInfo() << "total number of blocks to send to dc" << nBlocks;
int bNum = 0;
DownloadResult res = DownloadResult::OK;
while (res != DownloadResult::ERROR && bNum < nBlocks) {
if ((res = sendNextAddress(bNum)) != DownloadResult::ERROR) {
if ((res = sendNextDataBlock(b, bNum)) != DownloadResult::ERROR) {
bNum += 1;
}
}
}
if (res != DownloadResult::ERROR) {
bl_sendLastBlock();
}
return res;
}
bool hwapi::startBootloader() const {
qDebug() << "starting bootloader...";
int nTry = 5;
while (--nTry >= 0) {
bl_startBL();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
if (bl_isUp()) {
qInfo() << "starting bootloader...OK";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
return true;
}
}
qCritical() << "starting bootloader...FAILED";
return false;
}
bool hwapi::stopBootloader() const {
qDebug() << "stopping bootloader...";
int nTry = 5;
while (--nTry >= 0) {
bl_stopBL();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
if (!bl_isUp()) {
qInfo() << "stopping bootloader...OK";
return true;
}
}
qCritical() << "stopping bootloader...FAILED";
return false;
}
// br is a index into a table, used for historical reasons.
bool hwapi::openSerial(int br, QString baudrate, QString comPort) const {
qDebug() << "opening serial" << br << baudrate << comPort << "...";
if (dc_openSerial(br, baudrate, comPort, 1)) { // 1 for connect
qInfo() << "opening serial" << br << baudrate << comPort << "...OK";
return true;
}
qCritical() << "opening serial" << br << baudrate << comPort << "...FAILED";
return false;
}
bool hwapi::closeSerial(QString comPort) const {
qDebug() << "closing serial" << comPort << "...";
if (dc_closeSerial()) {
qInfo() << "closing serial" << comPort << "...OK";
return true;
} else {
qCritical() << "closing serial" << comPort << "...FAILED";
}
return false;
}
bool hwapi::resetDeviceController() const {
qDebug() << "resetting device controller...";
if (stopBootloader()) { // first stop a (maybe) running bootloader
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
dc_OrderToReset();
// wait maximally 3 seconds, before starting bootloader
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
qInfo() << "resetting device controller...OK";
return true;
}
return false;
}
QByteArray hwapi::loadBinaryDCFile(QString filename) const {
qDebug() << "loading dc binary" << filename << "...";
QFile file(filename); // closed in destructor call
if (!file.exists()) {
qCritical() << file.fileName() << "does not exist";
return QByteArray();
}
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "cannot open file" << file.fileName();
return QByteArray();
}
qInfo() << "loading dc binary" << filename << "...OK";
return file.readAll();
}
bool hwapi::downloadBinaryToDC(QString const &bFile) const {
qDebug() << "sending" << bFile << "to dc...";
QByteArray const dcBinary = loadBinaryDCFile(bFile);
if (dcBinary.size() > 0) {
if (dc_downloadBinary(dcBinary) != DownloadResult::OK) {
qCritical() << "sending" << bFile << "to dc...FAILED";
return false;
} else {
qInfo() << "sending" << bFile << "to dc...OK";
}
} else {
qCritical() << "sending" << bFile << "to dc...FAILED";
qCritical() << "loading binary" << bFile << "FAILED";
return false;
}
return true;
}
/******************************************************************************/
//
// LEVEL 3: hwapi::dc_updateDC.
//
/******************************************************************************/
bool hwapi::dc_updateDC(QString bFile, QString br, QString serial) const {
if (!baudrateMap.contains(br)) { // sanity check
qCritical() << "passed wrong baudrate" << br;
return false;
}
qDebug() << "updating dc: " << bFile << br << serial << "...";
if (!openSerial(baudrateMap.value(br), br, serial)) {
return false;
}
if (!resetDeviceController()) {
closeSerial(serial);
return false;
}
if (!startBootloader()) {
closeSerial(serial);
return false;
}
if (!downloadBinaryToDC(bFile)) {
stopBootloader();
closeSerial(serial);
qCritical() << "updating dc: " << bFile << br << serial << "...FAILED";
return false;
}
qInfo() << "updating dc: " << bFile << br << serial << "...OK";
stopBootloader();
closeSerial(serial);
return true;
}
/******************************************************************************/
//
// LEVEL 3: hwapi::dc_updatePrinterTemplate
//
/******************************************************************************/
bool hwapi::dc_updatePrinterTemplate(enum FileTypeJson type,
QVector<int> templatesIdx,
QVector<QString> fnames,
QString br,
QString serial) const {
// sanity checks
if (!baudrateMap.contains(br)) {
qCritical() << "passed wrong baudrate" << br;
return false;
}
if (templatesIdx.size() != fnames.size()) {
qCritical() << "list sizes must be equal" << br;
return false;
}
if (!std::all_of(templatesIdx.cbegin(), templatesIdx.cend(),
[](int i) { return i >= 1 && i <= 32; })) {
qCritical() << "wrong template indices";
return false;
}
if (type != FileTypeJson::PRINTER) {
qCritical() << "wrong file type" << (uint8_t)type;
return false;
}
qDebug() << "updating: " << fnames << br << serial << "...";
if (!serial.isNull()) {
if (!openSerial(baudrateMap.value(br), br, serial)) {
return false;
}
}
int nTry = 50;
while (!sys_ready4sending()) { // wait max. 5 seconds
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (--nTry <= 0) {
qCritical() << "sys not ready for sending";
if (!serial.isNull()) {
closeSerial(serial);
}
return false;
}
}
bool ret = true;
for (int i = 0; i < fnames.size(); ++i) {
QFile file(fnames[i]);
if (file.exists() && file.open(QIODevice::ReadOnly)) {
QByteArray ba = file.readAll();
if (ba.size() <= 800) { // max. size is 800 bytes
if (sys_sendJsonFileToDc((uint8_t)(type),
templatesIdx[i],
(uint8_t *)ba.data())) {
std::this_thread::sleep_for(std::chrono::seconds(1));
qInfo() << "sent file" << fnames[i] << "to dc";
}
}
} else {
qCritical() << fnames[i] << "!!! does not exist!!!";
ret = false;
continue;
}
}
if (!serial.isNull()) {
closeSerial(serial);
}
return ret;
}
bool hwapi::dc_printTemplate(enum FileTypeJson type,
QVector<int> templateIdx,
QString br,
QString serial) const {
// sanity checks
if (!baudrateMap.contains(br)) {
qCritical() << "passed wrong baudrate" << br;
return false;
}
if (!std::all_of(templateIdx.cbegin(), templateIdx.cend(),
[](int i) { return i >= 1 && i <= 32; })) {
qCritical() << "wrong template indices";
return false;
}
if (type != FileTypeJson::PRINTER) {
qCritical() << "wrong file type" << (uint8_t)type;
return false;
}
qDebug() << "printing: " << templateIdx << br << serial << "...";
if (!serial.isNull()) {
if (!openSerial(baudrateMap.value(br), br, serial)) {
return false;
}
}
int nTry = 50;
while (!sys_ready4sending()) { // wait max. 5 seconds
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (--nTry <= 0) {
qCritical() << "sys not ready for sending";
if (!serial.isNull()) {
closeSerial(serial);
}
return false;
}
}
bool ret = true;
struct T_dynDat dynTicketData;
memset (&dynTicketData, 0x00, sizeof(dynTicketData));
// lassen sich auch veraendern
memcpy(&dynTicketData.licensePlate[0], "WEN1230", 8);
memcpy(&dynTicketData.vendingPrice[0], "1234", 8);
memcpy(&dynTicketData.parkingEnd[0], "12:00:00", 8);
memcpy(&dynTicketData.currentTime[0], "14:15:00", 8);
memcpy(&dynTicketData.currentDate[0], "01.01.2023", 8);
for (int i = 0; i < templateIdx.size(); ++i) {
// dynamische Daten werden gespeichert
if (prn_sendDynamicPrnValues(&dynTicketData.licensePlate[0])) {
// angabe welches template beim drucken benutzt werden soll
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if (prn_printTemplate(templateIdx[i])) {
qDebug() << "printing template" << templateIdx[i];
std::this_thread::sleep_for(std::chrono::seconds(3));
}
} else {
ret = false;
continue;
}
}
if (!serial.isNull()) {
closeSerial(serial);
}
return ret;
}
// ------------------------------------------------------------------------------
// Level 1, control device-controller (functions of µC)
// check serial connection to deviceController
// read response from DC2 (input data)
// some test function for serial communication
// also Bootloader is here
// ------------------------------------------------------------------------------
void hwapi::dc_requTestResponse() const
{
sendWRcmd_setSendCommand0(SENDDIRCMD_TestSerial);
}
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
sendWRcmd_setSendCommand4(SENDDIRCMD_setWakeFrequ, period,0,0,0);
}
void hwapi::dc_OrderToReset(void) const
{
uint8_t len, buf[160];
len=dcBL_restartDC(buf);
sendWRcmd_setSendBlock160(len, buf);
//sendWRcmd_setSendCommand0(SENDDIRCMD_MakeReset);
// not needed, sendWRcmd_setSendBlock160() starts sending as well...
}
QString hwapi::dc_getSerialState(void) const
{
// geht
return epi_getTxt4comStateLine();
}
void hwapi::dc_clrSerialStateText(void) const
{
epi_clrTxt4comStateLine();
}
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_loadGenerals(0);
}
QString hwapi::dc_getSWversion(void) const
{
return epi_loadGenerals(1);
}
QString hwapi::dc_getState(void) const
{
return epi_loadGenerals(2);
}
// ------------------------------------------------------------------------------
// Level 2 DC2-onboard devices
// WR: set time
// RD. get time, get measure, get test results
// ------------------------------------------------------------------------------
// get UID, get time/date test results memory, RTC analog values
// ----------------------------------------------------------------------------------------------------------
// 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
{
sendWRcmd_setSendCommand0(SENDDIRCMD_setTime);
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;
}
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;
}
// ------------------------------------------------------------------------------
// Level 3: digital outputs and simple switching of connected devices
// simple processes like flashing a led or open flap for 1s
// ------------------------------------------------------------------------------
// Locks:
uint8_t hwapi::lock_switchUpperLock(uint8_t dir) const
{
// dir 0=off 1=up 2=down
sendWRcmd_setSendCommand4(SENDDIRCMD_MOVEUP_LOCK ,dir,0,0,0);
return 0;
}
uint8_t hwapi::lock_switchLowerLock(uint8_t dir) const
{
// dir 0=off 1=up 2=down
sendWRcmd_setSendCommand4(SENDDIRCMD_MOVEDN_LOCK ,dir,0,0,0);
return 0;
}
void hwapi::lock_switchVaultDoor(void) const
{
sendWRcmd_setSendCommand0(SENDDIR_OPENVAULT);
}
void hwapi::coin_switchRejectMotor(uint8_t dir) const
{
sendWRcmd_setSendCommand4(SENDDIR_REJMOT_ON, dir, 0,0,0);
}
void hwapi::coin_rejectCoins(void) const
{
sendWRcmd_setSendCommand0(SENDDIR_REJMOT_RUN);
}
void hwapi::led_switchLedService(uint8_t on) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_LEDINSIDE, on, 0, 0, 0);
}
void hwapi::led_switchLedPaper(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_LEDTICKET, on, ton, tof, 0);
}
void hwapi::led_switchLedPinPad(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_LEDPAD, on, ton, tof, 0);
}
void hwapi::led_switchLedStart(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_LEDSTART, on, ton, tof, 0);
}
void hwapi::led_switchLedCoinbassin(uint8_t on, uint8_t ton, uint8_t tof) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_LEDCOIN, on, ton, tof, 0);
}
void hwapi::fan_switchFan(bool on) const
{
//return epi_storeDOsToSend(DOBYTE3, FAN_ON, on);
sendWRcmd_setSendCommand4(SENDDIRCMD_FAN, on, 0, 0, 0);
}
void hwapi::alarm_switchSiren(bool on) const
{
//return epi_storeDOsToSend(DOBYTE4, LAERM, on);
sendWRcmd_setSendCommand4(SENDDIRCMD_LAERM, on, 0, 0, 0);
}
void hwapi::bar_OpenBarrier(bool open) const
{
//return epi_storeDOsToSend(DOBYTE4, REL1, open);
sendWRcmd_setSendCommand4(SENDDIRCMD_REL1, open, 0, 0, 0);
}
void hwapi::ptu_switchWake(bool WAKEACTIVE) const
{
//return epi_storeDOsToSend(DOBYTE1, CTS_PTU, WAKEACTIVE);
sendWRcmd_setSendCommand4(SENDDIRCMD_WAKEPTU, WAKEACTIVE,0,0,0);
}
// AUX-IO's or barcode reader
void hwapi::aux_power(bool on) const
{
// return epi_storeDOsToSend(DOBYTE2, BARC_POW_ON, on);
sendWRcmd_setSendCommand4(SENDDIRCMD_AUXPWR, on,0,0,0);
}
void hwapi::aux_setUsage(uint8_t PinDirection) const
{
// bit 0= Aux1 bit5=Aux6 1=output 0=input with pullup
// return epi_storeDOsToSend(DOBYTE6, nr, PinDirection);
sendWRcmd_setSendCommand4(SENDDIRCMD_AUXDDR, 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
//return epi_storeDOsToSend(DOBYTE5, nr, PinIsHigh);
sendWRcmd_setSendCommand4(SENDDIRCMD_AUXOUT, PinIsHigh,0,0,0);
}
void hwapi::lock_switchContactPower(bool on) const
{
//epi_storeDOsToSend(DOBYTE2, U_SW_ON, on);
sendWRcmd_setSendCommand4(SENDDIRCMD_UCONTACT_ON, 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
}
void hwapi::mif_readerOn(bool on) const
{
// DC2 also switches and enables serial driver
sendWRcmd_setSendCommand4(SENDDIRCMD_MIF_SWONOFF, on,0,0,0);
}
void hwapi::mif_creatAtbCard(uint8_t cardType) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MIF_SWONOFF, cardType, 0,0,0);
}
void hwapi::mod_switchPower(bool on) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MOD_SWONOFF, on,0,0,0);
}
void hwapi::mod_switchWake(bool WAKEACTIVE) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MOD_WAKE, WAKEACTIVE,0,0,0);
}
void hwapi::mdb_switchPower(bool on) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_POWER, on,0,0,0);
}
void hwapi::mdb_switchWake(bool WAKEACTIVE) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_WAKE, WAKEACTIVE,0,0,0);
}
void hwapi::credit_switchPower(bool on) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_CRED_ON, on,0,0,0);
}
void hwapi::credit_switchWake(bool WAKEACTIVE) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_CRED_WAKE, WAKEACTIVE,0,0,0);
}
void hwapi::shut_move(bool open) const
{
// true:open false:close
sendWRcmd_setSendCommand4(SENDDIRCMD_SHUT_MOV, open, 0,0,0);
}
void hwapi::esc_moveFlaps(uint8_t flap ) const
{
// 0: close both 1: open take-flap 2: open return
sendWRcmd_setSendCommand4(SENDDIRCMD_ESCRO_MOV, flap, 0,0,0);
}
// ------------------------------------------------------------------------------
// Level 3: digital inputs of connected devices
// ------------------------------------------------------------------------------
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;
}
bool hwapi::door_isLowerDoorOpen(void) const
{
uint8_t ret;
ret= epi_getDI_doorSwitches();
// bit0: upper door 1: low door 2:vault door
if (ret & 2)
return true;
return false;
}
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;
}
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;
}
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();
}
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();
}
bool hwapi::cash_getRejectMotorHomePos(void) const
{
return epi_getDI_rejectMotor_homepos();
}
uint8_t hwapi::cash_getLowPaperSensor(void) const
{
// 0: Sensor sees paper 1: no paper 99: off
return epi_getDI_npe_sensor();
}
// ------------------------------------------------------------------------------
// Level1,2,3 RD request commands
// ------------------------------------------------------------------------------
// the following requests can be sent manually
// or automatically in background by: void hwapi::dc_autoRequest(bool on)
// in other words:
// if automatic-reading is on then there's no need to send any of these commands!
void hwapi::request_DC2serialConfig() const
{
sendWRcmd_setSendCommand0(SEND_REQU_SERCONF);
}
void hwapi::request_DC2_HWversion() const
{
sendWRcmd_setSendCommand0(SEND_REQU_HWversion);
}
void hwapi::request_DC2_SWversion() const
{
sendWRcmd_setSendCommand0(SEND_REQU_SWversion);
}
void hwapi::request_DC2_condition() const
{
sendWRcmd_setSendCommand0(SEND_REQU_CONDITION);
}
void hwapi::request_DC2_UID() const
{
sendWRcmd_setSendCommand0(SEND_REQU_UID);
}
void hwapi::request_DC2_TimeAndDate() const
{
sendWRcmd_setSendCommand0(SEND_REQU_TIME);
}
void hwapi::request_DC2_analogues() const
{
sendWRcmd_setSendCommand0(SEND_REQU_ANALOGS);
}
void hwapi::request_DC2_digitalInputs() const
{
sendWRcmd_setSendCommand0(SEND_REQU_DIG_INPUTS);
}
void hwapi::request_DC2_digitalOutputs() const
{
sendWRcmd_setSendCommand0(SEND_REQU_DIG_OUTPUTS);
}
// ------------------------------------------------------------------------------
// the folowing device state requests are deployed only if device is powered up:
void hwapi::request_PrinterHwState() const
{
sendWRcmd_setSendCommand0(SEND_REQU_PRN_STATE);
}
void hwapi::request_PrinterCurrentFonts() const
{
sendWRcmd_setSendCommand0(SEND_REQU_PRN_FONTS);
}
void hwapi::request_PrinterStateComplete() const
{
sendWRcmd_setSendCommand0(SEND_REQU_PRN_ALL);
}
void hwapi::request_MifareReaderState() const
{
sendWRcmd_setSendCommand0(SEND_REQU_MIFSTATE);
}
void hwapi::request_MifareCardType() const
{
//uint8_t blkAdr=0;
//sendWRcmd_setSendCommand4(SEND_REQU_MIFDATA, blkAdr,0,0,0);
sendWRcmd_setSendCommand0(SEND_REQU_MIFSTATE);
}
void hwapi::request_MifareAtbType() const
{
//sendWRcmd_setSendCommand0(SEND_REQU_MIF_ATB_TYPE);
sendWRcmd_setSendCommand0(SEND_REQU_MIFSTATE);
}
void hwapi::request_MifareID() const
{
uint8_t sequenceNumber=0;
sendWRcmd_setSendCommand4(SEND_REQU_MIFDATA, sequenceNumber,0,0,0); // 1st data = card sequence =blk nr (0...15)
}
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)
sendWRcmd_setSendCommand4(SEND_REQU_MIFDATA, dataBlockNumber,0,0,0); // 1st data = card sequence =blk nr (0...15)
}
void hwapi::request_MDB_Status() const
{
sendWRcmd_setSendCommand0(SEND_REQU_MDB_GETSTAT);
}
//void hwapi::request_MDB_wakeInLine() const
//{
// sendWRcmd_setSendCommand0(SEND_REQU_MDB_GETWAK);
//}
void hwapi::request_MDB_lastResponse() const
{
sendWRcmd_setSendCommand0(SEND_REQU_MDB_GETRESP);
}
void hwapi::request_EMP_allParameters() const
{
sendWRcmd_setSendCommand0(SEND_REQU_EMP_GETALL);
}
void hwapi::request_EMP_lastCoin() const
{
sendWRcmd_setSendCommand0(SEND_REQU_EMP_GETCOIN);
}
// ------------------------------------------------------------------------------
// Level 3: readback digital outputs of connected devices
// these functions are not needed for normal operation
// but can be used to test and verify conditions
// There are two options:
// 1) the important things like power-outputs and wake lines are
// measured at DC2-terminals (after transistors) and come as input to DC-board
// 2) others like Leds are read from µC-pins by DC-board
// ------------------------------------------------------------------------------
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();
}
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;
epi_store64ByteSendData(6, buf);
sendWRcmd_setSendCommand0(SENDDIRCMD_DEVICE_PARA);
}
void hwapi::request_ReadbackDeviceSettings() const
{
sendWRcmd_setSendCommand0(SEND_REQU_DEVICE_PARA);
}
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);
epi_store64ByteSendData(42, buf);
sendWRcmd_setSendCommand0(SENDDIRCMD_MACHINE_ID);
}
void hwapi::request_ReadbackMachineID() const
{
sendWRcmd_setSendCommand0(SEND_REQU_MACINE_ID);
}
void hwapi::readback_machineIDdata(uint8_t *length, uint8_t *data) const
{
epi_restoreMachineIDsettings(length, data);
/*
buf66[0]=swl_getOneByteFromUint(machPara.customerNumber, GETLOWBYT);
buf66[1]=swl_getOneByteFromUint(machPara.customerNumber, GETHIGHBYT);
buf66[2]=swl_getOneByteFromUint(machPara.machineNumber, GETLOWBYT);
buf66[3]=swl_getOneByteFromUint(machPara.machineNumber, GETHIGHBYT);
buf66[4]=swl_getOneByteFromUint(machPara.borough, GETLOWBYT);
buf66[5]=swl_getOneByteFromUint(machPara.borough, GETHIGHBYT);
buf66[6]=swl_getOneByteFromUint(machPara.zone, GETLOWBYT);
buf66[7]=swl_getOneByteFromUint(machPara.zone, GETHIGHBYT);
buf66[8]=swl_getOneByteFromUint(machPara.alias, GETLOWBYT);
buf66[9]=swl_getOneByteFromUint(machPara.alias, GETHIGHBYT);
for (pp=0; pp<32; pp++)
buf66[10+pp]=machPara.location[pp];
dc2prot_setReadData(42, buf66);
*/
}
// ....................................................................................
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
{
//bool sendWRcmd_setSendCommand4(uint16_t nextCmd, uint8_t dat1, uint8_t dat2, uint8_t dat3, uint8_t dat4);
// commands are defined in PIdefines.h
sendWRcmd_setSendCommand4(SENDDIRCMD_OPENUP_DOOR, 1, 0, 0, 0);
// paras: dat2: 1=upper door lock 2=lower
// dat1: 1=open 2=close
return 0;
}
uint8_t hwapi::lock_closeUpperDoor(void) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_OPENUP_DOOR, 2, 0, 0, 0);
return 0;
}
uint8_t hwapi::lock_openLowerDoor(void) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_OPENDN_DOOR, 1, 0, 0, 0);
return 0;
}
uint8_t hwapi::lock_closeLowerDoor(void) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_OPENDN_DOOR, 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;
sendWRcmd_setSendCommand4(SENDDIRCMD_SHUTOPENBYTIME, 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;
sendWRcmd_setSendCommand4(SENDDIRCMD_SHUTOPENBYCOIN, 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
//sendWRcmd_setSendCommand4(SENDDIRCMD_SHUT_SENDTIME, timeIn100ms,0,0,0);
hwapi_shutterTime=timeIn_ms;
}
void hwapi::esc_takeMoney(void) const
{
// and close automatically after escrow time (1s)
sendWRcmd_setSendCommand0(SENDDIRCMD_ESCRO_TAKE);
}
void hwapi::esc_returnMoney(void) const
{
// and close automatically after time
sendWRcmd_setSendCommand0(SENDDIRCMD_ESCRO_GIVE);
}
// ----------------------------------------------------------------------------------------------------------
// --------------------------------------------- MIFARE -----------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
uint8_t hwapi::mif_returnReaderStateAndCardType(uint8_t *buf, uint8_t maxBufferSize) const
{
// retval 0=OK 1=error host buffer too small
/* data description:
new fast version:
byte 0= still the same: current read state:
0=power off 1=reader-fault 2=ready
3=just reading 4=read complete
5=read partial, removed too early
6=state unknown
byte 1: reader state 1=ok 0=nok
byte 2: card present (0,1)
byte 3: card selected (0)
byte 4: card type: 0...5
byte 5: card allowed (0=no 1=MifareClassic 1k or 4k)
byte 6: CardSize: 1 or 4 (kB)
byte 7: length of UID 4 or 7 (byte)
*/
return epi_restoreMifState(buf, maxBufferSize);
}
/* OLD data description:
byte 0: current read state: 0=power off 1=reader-fault 2=ready
3=just reading 4=read complete
5=read partial, removed too early
6=state unknown
byte 1,2: read data length from card
3: 1=reader is OK (reported serial nr is OK) 0=wrong or no reader
4...15: reader version, expected "ATB25-1.8"
16: 1=card is present 0:not
17: 0
18: card type reported from reader
19: 1=allowed card type 0=not
20: card size: 1 or 4 (dec) = card size
21: LengthOfUID: 4 or 7 (dec) (byte)
22: UID 8 byte in hex
byte 30: sector logged: 0
byte 31: current sector: 0
byte 32: result, always 0
*/
bool hwapi::mif_readerIsOK(void) const
{
uint8_t buf[40]; // old version had 40 bytes, new version only 8
uint8_t ret= epi_restoreMifState(buf, 40);
if (ret==0 && buf[0]>1 && buf[1]>0)
return 1;
return 0; // error
}
bool hwapi::mif_cardAttached(void) const
{
uint8_t buf[40];
uint8_t ret= epi_restoreMifState(buf, 40);
if (ret==0 && buf[0]>1 && buf[2]>0) // reader OK
if (buf[16]>0)
return 1;
return 0; // error
}
uint8_t hwapi::mif_readResult(void) const
{
// result: 0: unknown or still in progress
// 1: card read successful
// 2: reading error
uint8_t buf[40];
uint8_t ret= epi_restoreMifState(buf, 40);
// data read successful && Reader OK && card attached && ...
if (ret==0 && buf[1]>0 && buf[2]>0)
{
// byte 0: current read state: 0=power off 1=reader-fault 2=ready
// 3=just reading 4=read complete
// 5=read partial, removed too early
// 6=state unknown
if (buf[0]==1 || buf[0]==5 || buf[0]==6)
return 2;
if (buf[0]==4)
return 1;
}
return 0; // error
}
QString hwapi::mif_cardUID(void) const
{
QString myStr;
uint8_t buf[65], ret;
//uint8_t ret= epi_restoreMifState(buf, 40);
myStr.clear();
/*
if (ret==0 && buf[0]==4 && buf[3]>0 && buf[16]>0 && buf[19]>0)
{
// UID in buf[22...29]
for (int ii=0;ii<8; ii++)
{
myStr+=QString::number(buf[ii+22],16);
myStr+=" "; // make a gap between numbers
}
}
*/
ret=epi_restoreMifData(0, buf, 64);
if (ret)
return myStr; // return empty string on error
else
{
buf[8]=0;
//myStr.append(buf);
for (int ii=0;ii<8; ii++)
{
myStr+=QString::number(buf[ii],16); // 16: return in hex format
myStr+=" "; // make a gap between numbers
}
return myStr;
}
}
uint8_t hwapi::mif_getCardDataDec(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize) const
{
// blkNr=0...11 return buf[64] maxBufferSize must be >=64
return epi_restoreMifData(blkNr, buf, maxBufferSize);
// blkNr=0...11 return buf[64]
}
QString hwapi::mif_getCardDataStr(uint8_t blockNumber) const
{
// with blockNumber=0...11
QString myStr;
uint8_t buf[66];
myStr.clear();
if (blockNumber>11)
return myStr;
epi_restoreMifData(blockNumber, buf, 66);
for (int ii=0; ii<64; ii++)
{
//myStr+=QString::number(buf[ii],10); // decimals as ascii
myStr+=QString::number(buf[ii],16); // hex numbers as ascii
myStr+=" "; // make a gap between numbers
}
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?
uint8_t prnHWstate[20];
epi_restorePrinterState(prnHWstate);
// byte 1...6 come right from printer, see printer manual
// byte 0 = all important infos:
// byte 0 = 0: prnter OK, >0: error
// bit0: paper low 1: no paper 2: temperature error
// 3: head open 4: paper jam in cutter
// 6: no response 7: bad response from printer
prn_hw_state->powerRdBk = epi_getDI_printerPwr();
prn_hw_state->rsSwOk = epi_getDO_serialMux1isSetToPrinter(); // mux1 off: serial is switched to printer
prn_hw_state->rsDrvOk = epi_getDO_serialDriverIsOn();
prn_hw_state->ReadyLine = epi_getDI_prnReady();
if (prnHWstate[0]==0)
prn_hw_state->inIdle = true; // no errors
else
prn_hw_state->inIdle = false; // off or errors
if (prnHWstate[0] & 1)
prn_hw_state->paperNearEnd=true;
else
prn_hw_state->paperNearEnd = false;
if (prnHWstate[0] & 2)
prn_hw_state->noPaper=true;
else
prn_hw_state->noPaper = false;
if (prnHWstate[0] & 4)
prn_hw_state->ErrorTemp=true;
else
prn_hw_state->ErrorTemp = false;
if (prnHWstate[0] & 8)
prn_hw_state->HeadOpen=true;
else
prn_hw_state->HeadOpen = false;
if (prnHWstate[0] & 16)
prn_hw_state->cutterJam=true;
else
prn_hw_state->cutterJam = false;
if (prnHWstate[0] & 64)
prn_hw_state->noResponse=true;
else
prn_hw_state->noResponse = false;
if (prnHWstate[0] & 128)
prn_hw_state->badResponse=true;
else
prn_hw_state->badResponse = false;
return prnHWstate[0];
}
bool hwapi::prn_isUpAndReady(void) const
{
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
{
sub_storeSendingText(buf);
epi_storeUserOfSendingTextBuffer(1,0,0,0,0); // 1=print text
}
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);
}
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
sendWRcmd_setSendCommand4(SENDDIRCMD_PRN_ESC_CMD, 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;
epi_store64ByteSendData(5, buf);
sendWRcmd_setSendCommand0(SENDDIRCMD_PRN_SETUP);
}
void hwapi::prn_movePaper(uint8_t wayInMm, uint8_t direction) const
{
//direction: 1=forward 2=backward
sendWRcmd_setSendCommand4(SENDDIRCMD_PRN_MOVE, 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
sendWRcmd_setSendCommand4(SENDDIRCMD_PRN_SETFONT, font, size, width, height);
}
void hwapi::prn_setLetters(uint8_t bold, uint8_t invers, uint8_t underlined) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_PRN_SETLETT, bold, invers, underlined, 0);
}
void hwapi::prn_cut(uint8_t kindof) const
{
// kindof = 1: full cut 2: partial cut 3=eject (5xLF + full cut)
sendWRcmd_setSendCommand4(SENDDIRCMD_PRN_CUT, kindof,0,0,0);
}
void hwapi::prn_newLine(uint8_t nrOfLines) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_PRN_LF, nrOfLines, 0, 0, 0);
}
void hwapi::prn_printCompleteFontTable(void) const
{
sendWRcmd_setSendCommand0(SENDDIRCMD_PRN_FONTTAB);
}
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];
epi_store64ByteSendData( (5+dataLeng), buf);
sendWRcmd_setSendCommand0(SENDDIRCMD_PRN_BC);
}
void hwapi::prn_sendQRdata(QByteArray *buf) const
{
// maximal 150 alphanummeric bytes
sub_storeSendingText(buf);
epi_storeUserOfSendingTextBuffer(2,0,0,0,0); // 2= print QRcode
}
void hwapi::prn_printQRcode(void) const
{
// which was sent before
sendWRcmd_setSendCommand0(SENDDIRCMD_PRN_QR);
}
void hwapi::prn_printLogo(uint8_t nrOfLogo, uint8_t offset ) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_PRN_LOGO_FL, nrOfLogo, offset, 0, 0);
pri_TD_addText("Hallo");
}
// .........................................................
// Parking Ticket (print out) designer
// .........................................................
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
/* complete list of possible commands:
group 50 : paper
attribute 10 : move forward
p1: wayInMm p2: direction
attribute 11 : cut
p1: kind of, 1=full 2=partial, 3=eject
attribute 12 : new line(s)
p1: nr of lines 1...100
group 51 : fonts
attribute 10 : kind of font see description above
p1: possible: 0...22, expedient: 5...11
attribute 11 : font size
p1: 6...20 12=normal 6=tiny
attribute 12 : font width
p1: 0...4
attribute 13 : font heigth
p1: 0...7
attribute 14 : switch bold print on/off
p1: 0=off 1=on
attribute 15 : switch invers print on/off
p1: 0=off 1=on
attribute 16 : switch underlined print on/off
p1: 0=off 1=on
group 52 : print graphics
attribute 10 : print barcode with dynamic data 6 and 7
p1...p5 = kindOf, withText, offset, rotation, dataLeng, see description above
attribute 11 : print QRcode with preset data
attribute 12 : print Logo
p1=nrOfLogo, p2=offset
group 53 : print dynamics
attribute 10 : 1...8 = print dynData 0..7 at this place
*/
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);
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);
}
#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);
}
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);
}
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];
}
// ----------------------------------------------------------------------------------------------------------
// --------------------------------------------- Coin Checker -----------------------------------
// ----------------------------------------------------------------------------------------------------------
void hwapi::emp_sendSettings(uint16_t coinAcceptance, uint8_t tokenChannel, uint16_t *coinDenomination ) const
{
// coinAcceptance: bit0=coin1 (lowest donomination) 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;
}
epi_store64ByteSendData(35, myBuf);
sendWRcmd_setSendCommand0(SENDDIRCMD_EMP_SETT);
}
void hwapi::emp_pollingOnOff(uint8_t on) const
{
// on: 1=start polling the coin accepter 0=stop
sendWRcmd_setSendCommand4(SENDDIRCMD_EMP_POLL, on,0,0,0);
}
void hwapi::emp_startCoinAcceptance(void) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_EMP_STARPPAY, 0,0,0,0);
}
void hwapi::emp_stopCoinAcceptance(void) const
{
sendWRcmd_setSendCommand4(SENDDIRCMD_EMP_STOPPAY, 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]);
}
/*
static bool emp_newCoin;
static uint8_t emp_newCoinSignal;
static uint16_t emp_newCoinValue;
static uint8_t emp_newCoinError;
uint8_t hwapi::emp_chkIfCoinInserted(void)
{
// retval: 1=got coin 0xFF=emp reported an error 0=got nothing
// comes only one time after each coin, vaslues are stored
uint8_t leng, data[8];
epi_restoreEmpCoinSignal(&leng, data);
// 5 byte per inserted coin:
// data[0]: 1=got coin, data set valid
// data[1]: emp-signal of last inserted coin
// data[2]: emp-error or warning
// data[3,4]: emp-value of last inserted coin 3=low byte
//epi_clearEmpCoinSignal();
if (data[0]>0)
{
emp_newCoin=data[0]; // anything came in, coin or error or both
if (data[0] & 0x80)
{
emp_newCoinError=data[4];
}
if (data[0] &0x0F)
{
emp_newCoinSignal=data[1];
emp_newCoinValue=uchar2uint(data[3], data[2]);
}
return emp_newCoin;
}
return 0;
}
uint8_t hwapi::emp_getInsertedCoinSignal(void)
{
uint8_t uctmp=emp_newCoinSignal;
emp_newCoinSignal=0; // return only once
return uctmp;
}
uint16_t hwapi::emp_getInsertedCoinValue(void)
{
uint16_t uitmp=emp_newCoinValue;
emp_newCoinValue=0; // return only once
return uitmp;
}
uint8_t hwapi::emp_getCoinError(void)
{
uint8_t uctmp=emp_newCoinError;
emp_newCoinError=0; // return only once
return uctmp;
}
*/
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;
}
// ----------------------------------------------------------------------------------------------------------
// --------------------------------------------- Bill Validator -----------------------------------
// ----------------------------------------------------------------------------------------------------------
/*
// Coin checker and changer mdb4.2 / section 5
// Level 2 Commands (predefined device msg acc. mdb manual and auto-poll)
uint8_t hwapi::mdb_bill_startPolling(bool on)
{
// send ether one command (from list below)
// or a poll command in the proper polling grid (e.g. every 100ms)
epi_storeConfig08(mdbPollBills,on);
//sendWRcmd_setSendCommand0(SENDDIRCMD_WR_CONF_08);
return 0;
}
// the following functions tell the DC to send a mdb command to any mdb slave
// in opposite to mdb_sendData() the exact telegrams don't have to be formed here, DC does it.
uint8_t hwapi::mdb_bill_reset()
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_BillAll, 1, 0, 0, 0);
return 0;
}
uint8_t hwapi::mdb_bill_setup()
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_BillAll, 2, 0, 0, 0);
return 0;
}
uint8_t hwapi::mdb_bill_security(uint16_t secLevel)
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_BillAll, 3, uint8_t(secLevel), uint8_t(secLevel>>8), 0);
return 0;
}
uint8_t hwapi::mdb_bill_pollManually(void)
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_BillAll, 4, 0, 0, 0);
return 0;
}
uint8_t hwapi::mdb_bill_billType(uint16_t billEnable, uint16_t escrowEnable)
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_BillType,
uint8_t(billEnable), uint8_t(billEnable>>8),
uint8_t(escrowEnable), uint8_t(escrowEnable>>8));
return 0;
}
uint8_t hwapi::mdb_bill_escrow(uint8_t action)
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_BillAll, 5, action, 0, 0);
return 0;
}
uint16_t hwapi::mdb_bill_stacker(void)
{
sendWRcmd_setSendCommand4(SENDDIRCMD_MDB_BillAll, 6, 0, 0, 0);
return 0;
}
uint8_t hwapi::mdb_bill_expansion(uint8_t subCmd, uint8_t send[32])
{
uint8_t sendbuf[34], nn;
// 1) insert subCmd into buffer
for (nn=0; nn<32; nn++)
sendbuf[nn+1]=send[nn];
sendbuf[0]=subCmd;
sendbuf[33]=0;
epi_storeMdbSendData(34, sendbuf);
sendWRcmd_setSendCommand0(SENDDIRCMD_MDB_BillExp);
return 0;
}
uint8_t hwapi::mdb_bill_gotPollResponse(void)
{
// 0: no response 1: got ACK 2: got NAK 3 got ACK with additional data
return epi_getMdbResponse(); // request only once, then epi_getMdbRecLength()==0
}
uint8_t hwapi::mdb_bill_getDataLen(void)
{
// return nr of byte received from any mdb device
return epi_getMdbRecLength();
}
uint8_t hwapi::mdb_bill_getPollData(uint8_t *mdb_data, uint8_t maxBufferSize)
{
uint8_t len, buf[64], LL;
len=epi_getMdbRecLength();
epi_restoreMdbRecData(buf); // request only once, then epi_getMdbRecLength()==0
(maxBufferSize<len)?LL=maxBufferSize:LL=len;
for (uint8_t nn=0; nn<LL; nn++ )
mdb_data[nn]=buf[nn];
return 0; // OK
}
*/
// ----------------------------------------------------------------------------------------------------------
// --------------------------------------------- MODEM ------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------
/*
uint8_t hwapi::mod_getHwState(struct Tmod_hw_state *mod_hw_state)
{
mod_hw_state->powerRdBk=epi_restoreReadDIs(DIBYTE0, RB_VGSM);
if (epi_cntchk_swRs1toModem())
mod_hw_state->rsSwOk=1;
else
mod_hw_state->rsSwOk=0;
mod_hw_state->rsDrvOk=epi_cntchk_enabDrv01(); // can never be false
mod_hw_state->HwState=false;
mod_hw_state->CommState=false;
mod_hw_state->gotAnswer=false;
return 0;
}
uint8_t hwapi::mod_setCondition(uint16_t chgCmd)
{
// e.g. change to state registered, sleep, open, off....
return uint8_t(chgCmd);
}
uint16_t hwapi::mod_getCondition(void)
{
// e.g. now socket open
return 0;
}
bool hwapi::mod_sendBufferFree(void)
{
// sending allowed (before writing) and sending finished (after writing)
return 0;
}
void hwapi::mod_wantReadData(uint16_t nrOfData)
{
// start reading
nrOfData=0;
}
uint8_t hwapi::mod_sendDataBlk(uint16_t len, uint8_t *buf)
{
len=buf[0];
return uint8_t(len);
}
uint16_t hwapi::mod_gotData(void)
{
// return nr of received bytes
return 0;
}
uint8_t hwapi::mod_loadDataBlk(uint16_t len, uint8_t *buf)
{
len=buf[0];
return uint8_t(len);
}
uint8_t hwapi::mod_setupSerial(struct TserialParams serialParameter)
{
// Baudrate and so on...
return 0;
}
uint8_t hwapi::mod_getCurrentSerialSettings(struct TserialParams *serialParameter)
{
// Baudrate and so on...
return 0;
}
*/
// neu, 25.8.21
QString hwapi::dc_getTxt4RsDiagWin(void) const
{
return epi_getTxt4RsDiagWin();
}
void hwapi::dc_clrTxt4RsDiagWin(void) const
{
epi_clrTxt4RsDiagWin();
}
QString hwapi::dc_get2ndTxt4RsDiagWin(void) const
{
return epi_get2ndTxt4RsDiagWin();
}
void hwapi::dc_clr2ndTxt4RsDiagWin(void) const
{
epi_clr2ndTxt4RsDiagWin();
}
QString hwapi::dc_getTxt4HsStateLine(void) const
{
// Crash!
return epi_getTxt4HsStateLine();
}
void hwapi::dc_clrTxt4HsStateLine(void) const
{
epi_clrTxt4HsStateLine();
}
QString hwapi::dc_getTxt4masterStateLine(void) const
{
return epi_getTxt4masterStateLine();
}
void hwapi::dc_clrTxt4masterStateLine(void) const
{
epi_clrTxt4masterStateLine();
}
QString hwapi::dc_getTxt4resultStateLine(void) const
{
return epi_getTxt4resultStateLine();
}
void hwapi::dc_clrTxt4resultStateLine(void) const
{
epi_clrTxt4resultStateLine();
}
QString hwapi::dc_getdataStateLine(void) const
{
return epi_getTxt4dataStateLine();
}
void hwapi::dc_clrTxt4dataStateLine(void) const
{
epi_clrTxt4dataStateLine();
}
QString hwapi::dc_getdatifLine(void) const
{
return epi_getTxt4datifLine();
}
void hwapi::dc_clrTxt4datifLine(void) const
{
epi_clrTxt4datifLine();
}
// using DC2 Bootloader
void hwapi::bl_iniChain(void) const
{
dcBL_iniChain();
}
bool hwapi::bl_importBinFile(QByteArray readBinFile, uint32_t fileSize, char withDispl) const
{
return dcBL_importBinFile(readBinFile, fileSize, withDispl);
}
uint8_t hwapi::bl_activatBootloader(uint8_t *sendData) const
{
return dcBL_activatBootloader(sendData);
}
uint8_t hwapi::bl_startChain(void) const
{
return dcBL_startChain();
}
uint8_t hwapi::bl_readBLversion(uint8_t *sendData) const
{
// minimum size of sendData-buffer: 5byte retval: length
return dcBL_readBLversion(sendData);
}
uint8_t hwapi::bl_readFWversion(uint8_t *sendData) const
{
// minimum size of sendData-buffer: 5byte retval: length
return dcBL_readFWversion(sendData);
}
uint8_t hwapi::bl_prepareDC_BLcmd(uint8_t Cmd, uint8_t SendDataLength, uint8_t *sendData, uint8_t *outBuf) const
{
// 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);
}
uint8_t hwapi::bl_exitBL(uint8_t *sendData) const
{
// minimum size of sendData-buffer: 5byte retval: length
return dcBL_exitBL(sendData);
}
void hwapi::led_switchLedIllumination(uint8_t on) const
{
if (on)
{
}
}
// neu, 25.3.23
// ------------------------------------------------------------------------------------
// 27.3.2023: Use Device-Controller's Bootloader to send hex-file
// ------------------------------------------------------------------------------------
void hwapi::bl_rebootDC(void) const
{
uint8_t len, buf[20];
len=dcBL_restartDC(buf);
sendWRcmd_setSendBlock160(len, buf);
}
void hwapi::bl_startBL(void) const {
uint8_t len, buf[20];
memset(buf, 0x00, sizeof(buf));
len=dcBL_activatBootloader(buf);
sendWRcmd_setSendBlock160(len, buf);
}
bool hwapi::bl_checkBL(void) const
{
uint8_t len, buf[20];
//len=dcBL_readBLversion(buf);
len=dcBL_readFWversion(buf);
sendWRcmd_setSendBlock160(len, buf);
return (len > 0);
}
bool hwapi::bl_isUp(void) const
{
uint8_t receivedData[160];
uint8_t LL;
memset(receivedData, 0x00, sizeof(receivedData));
LL=epi_getRawRecLength();
if (LL>0)
{
epi_getRawReceivedData(receivedData);
//epi_clrRawReceivedString();
//qDebug() << " *** got " << LL << " data bytes from BL: " <<
// receivedData[0] << " " << receivedData[1] << " " << receivedData[2] << " " <<
// receivedData[3] << " " << receivedData[4] << " " << receivedData[5] << " ";
// response to "readFWversion"
if (receivedData[0]==2 && receivedData[1]==146 && receivedData[2]==45 &&
receivedData[3]==45 && receivedData[4] ==95 && receivedData[5]==176)
{
dcBL_iniLoading();
return true;
}
// response to "start BL"
if (receivedData[0]==2 && receivedData[1]==101 && receivedData[2]==48 &&
receivedData[3]==223 && receivedData[4] ==131 )
{
dcBL_iniLoading();
return true;
}
}
return false;
}
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
// uint8_t dcBL_sendFlashStartAddr2BL(uint32_t startAddr, uint8_t *sendData)
// minimum size of sendData-buffer: 13byte retval: length (9...13)
sendWRcmd_setSendBlock160(len, buf); // send command to BL
}
}
uint8_t hwapi::bl_wasSendingAddOK(void) const
{
// return val: 0: no response by now 1:error 10: OK
return dcBL_sendSuccess(0x21);
// return val: 0: no response by now 1:error 10: OK
// lastCommand=0x21 for sendAddr or 0x22 for send data
}
void hwapi::bl_openBinary(void) const
{
dcBL_loadBinary(0);
}
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);
/* hier ist alles richtig
qDebug() << "bl_sendDataBlock "<<LL<< " bytes: " << buffer[0] << " " << buffer[1] << " "
<< buffer[2] << " " << buffer[3] << " " << buffer[4] << " " << buffer[5] << " "
<< buffer[6] << " " << buffer[7] << " " << buffer[8] << " " << buffer[9] << " "
<< buffer[61] << " " << buffer[62] << " " << buffer[63] << " " << buffer[64] << " "
<< buffer[65] << " " << buffer[66] << " " << buffer[67] << " " << buffer[68] << " ";
*/
sendLen=dcBL_prepareDC_BLcmd(0x22, LL, buffer, sendBuf); // pack into protocol frame
/*
qDebug() << "bl_sendDataBlock "<<sendLen<< " bytes: " << sendBuf[0] << " " << sendBuf[1] << " "
<< sendBuf[2] << " " << sendBuf[3] << " " << sendBuf[4] << " " << sendBuf[5] << " "
<< sendBuf[6] << " " << sendBuf[68] << " " << sendBuf[69] << " " << sendBuf[70] << " "
<< sendBuf[71] << " " << sendBuf[72] << " " << sendBuf[73] << " " << sendBuf[74] << " ";
*/
sendWRcmd_setSendBlock160(sendLen, sendBuf); // send 140 bytes
delay(100);
}
void hwapi::bl_sendLastBlock(void) const
{
uint8_t len, buf[20];
len=dcBL_writeLastPage(buf);
sendWRcmd_setSendBlock160(len, buf);
}
uint8_t hwapi::bl_wasSendingDataOK(void) const
{
// return val: 0: no response by now 1:error 10: OK
return dcBL_sendSuccess(0x22);
// return val: 0: no response by now 1:error 10: OK
// lastCommand=0x21 for sendAddr or 0x22 for send data
}
void hwapi::bl_stopBL(void) const
{
uint8_t len, buf[20];
len=dcBL_exitBL(buf);
sendWRcmd_setSendBlock160(len, buf);
}
/*
bool hwapi::bl_isDiagAvailable(void) const
{
return dcBL_checkForText();
}
QString hwapi::dc_getDiagText(void) const
{
return dcBL_readText(); // read from 0...9 (oldest first)
}
*/
/*
// geht noch nicht //////
void hwapi::bl_startSending(void) const
{
dcBL_startLoading();
}
void hwapi::bl_sendFile(void) const
{
//qDebug()<<" HWAPI_BL_CYCL_ISrunning ";
dcBL_sendHexfile();
}
*/
// ------------------------------------------------------------------------------------
// 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;
/*
struct T_extTime
{
uint8_t Hours;
uint8_t Min;
uint8_t Sec;
uint8_t Year;
uint8_t Month;
uint8_t Day;
uint8_t DOW;
uint8_t res1;
uint16_t MinOfDay;
uint16_t res2;
uint32_t SecOfDay;
uint8_t isLeapYear;
uint8_t nxtLeapYear;
uint8_t lastLeapYear;
uint8_t hoursOfThisWeek;
uint16_t minutesOfThisWeek;
uint16_t hoursOfThisMonth;
uint16_t daysOfThisYear;
uint16_t GetHoursOfYear;
uint16_t res3;
uint32_t GetMinutesOfYear;
uint8_t getWakeIntvSec;
uint8_t res4;
uint16_t res5;
uint32_t MinutesOfMillenium;
};
*/
}
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=check4freeFDlongCmd();
// 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=check4freeFDlongCmd();
// 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;
}
//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
return longFDcmd_set(33,0,0, 64, temp);
}
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
// 3.5.23: die dynVals und alle templates sollen am stück gesendet
uint8_t data[64];
data[0]=nrOftemplate;
return longFDcmd_set(152, 0,0, 1, data);
}
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=check4freeFDshortCmd();
if (frei<8)
return false;
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.4
// 38: <100 to get long 64byte response
return ret;
}
bool hwapi::log_chkIfVaultRecordAvailable(void) const
{
// return true if completly received
return epi_checkIfVaultRecordAvailable();
return false;
}
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
{
uint16_t LL, nn, len;
char *start;
uint8_t buf[400];
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); // =320
start = &retVR->startbuffer[0];
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
return true;
}
bool hwapi::prn_printAccountReceipt(void) const
{
return sendFDcmd_set(154, 0,0, 0,0,0,0);
}
bool hwapi::prn_printTestTicket(void) const
{
// return true if sending to DC OK, false if cmd-stack is full
return sendFDcmd_set(157, 0,0, 0,0,0,0);
}
bool hwapi::cash_startPayment(uint32_t amount) const
{
// 17.4.23TS: extended to 32bit
uint8_t dat1, dat2, dat3, dat4;
hwapi_lastStartAmount=amount;
epi_clearCurrentPayment();
dat1=ulong2uchar(amount, 0);
dat2=ulong2uchar(amount, 1);
dat3=ulong2uchar(amount, 2);
dat4=ulong2uchar(amount, 3);
return sendFDcmd_set(155, 0,0, dat1,dat2,dat3,dat4);
}
uint32_t hwapi::getInsertedAmount(void) const
{
return epi_CurrentPaymentGetAmount();
}
uint16_t hwapi::getLastInsertedCoin(void) const
{
return epi_CurrentPaymentGetLastCoin();
}
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
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
emit hwapi_vendStopByPushbutton();
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
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
return sendFDcmd_set(156, 0,0, 2,0,0,0);
}
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, buf[8], nn;
char ctmp;
memset(buf, 0x00, sizeof(buf));
type=epi_mifGetCardType(&buf[0]);
//holder[8] = name of card holder
// retval Type of MifareCard, 1=upper door, 2=lower door 3=test printer 4=test coins
for (nn=0;nn<8; nn++) {
ctmp=buf[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);
}
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: unknown
// 1: OK - last template was printed succesful
// 2: error - last template was not printed
struct T_dynamicCondition dynMachCon;
//uint8_t buf[70], leng,
uint8_t res;
static uint8_t lastState;
//uint32_t aa;
// aa=&dynMachCon;
sys_getDynMachineConditions(&dynMachCon);
res= dynMachCon.resultOfLastTemplPrint;
// 0: unknown or printing in progress
// 1: OK, doc was printed 2: error, doc was not printed
if (res==0)
{
if (lastState>0)
{
// print was started
lastState=res;
}
} else
{
if (lastState==0)
{
// result hat sich auf 1 oder 2 geändert, d.h. Druck ist fertig
if (res==1)
{
//emit hwapi_templatePrintFinished_OK();
} else
if (res==2)
{
//emit hwapi_templatePrintFinished_Err();
}
lastState=res;
}
}
return res;
}
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;
// 2nd way to get dyn.conditions:
epi_restoreDynMachineConditions(&leng, buf);
lastPrinterStatus=buf[53];
return 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);
epi_store64BdevParameter(LL,buf); // this buffer holds the device settings to be used here in hwapi
epi_store64ByteSendData(LL, buf); // this buffer holds sending data temporarely
sendWRcmd_setSendCommand0(SENDDIRCMD_DEVICE_PARA);
}
void hwapi::sys_restoreDeviceParameter(struct T_devices *deviceSettings) const
{
uint8_t buf[64];
uint8_t LL, nn;
tslib_strclr(buf,0,64);
uint8_t *start;
epi_restore64BdevParameter(&LL, buf);
// Puffer in struct eintragen:
start = &deviceSettings->kindOfPrinter;
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
}
/* ---------------------------------------------------------------------------------------------
// ------------ supervise all hardware components
// ------------ assess the machine state
1. check if DC startup test is through, retrigger if not
2. get results and find errors
3. in case of error check if component is used (e.g. billreader is seldom used)
4: check doors
5. return value: 0: no response from DC
1: no Test results and Test not running. need retrigger!
2: state not clear by now, test ongoing, wait
3: Service or battery door is open, goto INTRUSION MODE
from here: after valid ID-card goto SERVICE MODE
4: vault door is open, goto INTRUSION MODE
from here: after valid ID-card and vault door closed goto TEST MODE
in TEST MODE: complete system check decides if vending mode allowed
5: All doors are closed but errors found,
goto OOO MODE (out-of-order)
from here: run system test until problem is fixed
6: All doors are closed, no error, maybe warnings,
goto VENDING MODE (normal operation)
(priority sinks from 0 to 6)
--------------------------------------------------------------------------------------------- */
uint8_t hwapi::sys_componentAssessment(void) const
{
// this function decides if vending mode is possible, independant from door
// return >0 in case of error
// is inncluded in sys_superviseSystem
struct T_moduleCondition *modCond=0;
sys_getDeviceConditions(modCond);
struct T_dynamicCondition *dynMaCond=0;
sys_getDynMachineConditions(dynMaCond);
struct T_devices *devPara=0;
sys_restoreDeviceParameter(devPara);
if (modCond->rtc>=200)
return 1;
if (modCond->printer==200 || modCond->printer==201) // 200: not connected 201: printer-HW-error 202: no paper
return 2;
if (modCond->printer==202)
return 3;
if (modCond->coinBlocker>=200)
return 4;
if (modCond->mdbBus>=200)
return 5;
if (modCond->intEe>=200)
return 6;
if (devPara->kindOfCoinChecker==1 || devPara->kindOfCoinChecker==2) // 0: without 1=EMP820 2=EMP900 3=currenza c² (MW)
{
if (modCond->coinChecker>=200 || modCond->coinEscrow>=200)
{
// Fehler Münzver.
return 7;
}
if (modCond->coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok
{
return 8;
}
} else
if (devPara->kindOfCoinChecker==3)
{
if (modCond->changer>=200)
{
// Fehler Münzver.
return 7;
}
if (modCond->coinSafe>200) // 200: kasse fehlt 201: voll 100:fast voll 1:ok
{
return 8;
}
}
if ( modCond->billReader>=200 && devPara->BillAcceptor>0)
{
// Fehler BNA
return 9;
}
if (dynMaCond->onAlarm>0)
return 10;
if (dynMaCond->modeAbrech>0)
return 11;
if (dynMaCond->nowCardTest>0)
return 12;
if (dynMaCond->startupTestIsRunning>0)
return 13;
if (modCond->voltage>=200)
return 14;
if (modCond->temper>=200)
return 15;
return 0;
}
// retrigger System-Check with:
// bool hwapi::sys_runCompleteTest(void) const
uint8_t hwapi::sys_superviseSystem(void) const
{
// this function proofs if vending is possible depending of doors state
struct T_dynamicCondition *dynMaCond=0;
struct T_moduleCondition *modCond=0;
if (!gpi_areDcDataValid())
{
// es gibt keinerlei gültige Daten vom DC
return 0;
}
// jetzt sind die DC-Daten aktuell, also reinholen:
sys_getDynMachineConditions(dynMaCond);
sys_getDeviceConditions(modCond);
if (!modCond->allModulesChecked)
{
// noch keine Testergebnisse
if (dynMaCond->startupTestIsRunning)
return 2; // Starttest läuft gerade
else
return 1; // Starttest ist noch nicht gelaufen
}
// all doors: 99: undefined 0:closed 1:open
if (dynMaCond->lowerDoor || dynMaCond->upperDoor)
return 3;
if (dynMaCond->middleDoor)
return 4;
if (sys_componentAssessment() >0)
return 5; // errors found
return 6; // everything fine
}
uint8_t hwapi::sys_getSystemErrors(void) const
{
return sys_componentAssessment();
}