
#ifndef hwapi_H
#define hwapi_H

#include <stdint.h>
#include <QObject>
#include "interfaces.h"
#include "datIf.h"

class QSharedMemory;
class hwapi :   public QObject,
                public hwinf
{
    Q_OBJECT
    Q_INTERFACES(hwinf)
private:
    void sub_storeSendingText(QByteArray *buf) const;

    DownloadResult sendNextAddress(int bNum) const;
    DownloadResult sendNextDataBlock(QByteArray const &b, int bNum) const;
    DownloadResult sendStatus(int ret) const;
    DownloadResult dc_downloadBinary(QByteArray const &binary) const;

    bool startBootloader() const;
    bool stopBootloader() const;
    bool openSerial(int br, QString baudrate, QString comPort) const;
    bool closeSerial(QString comport) const;
    bool resetDeviceController() const;
    QByteArray loadBinaryDCFile(QString filename) const;
    bool downloadBinaryToDC(QString const &bFile) const;

    QSharedMemory *m_sharedMem;
public:
    explicit hwapi(QObject *parent = nullptr);
    virtual ~hwapi();

    T_datif *myDatif;


    virtual QStringList dc_getStatus() const override;

    // ------------------------------------------------------------------------------
    // 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 dc_openSerial(int BaudNr, QString BaudStr, QString ComName, uint8_t connect) const override;
        // BaudNr:  0:1200   1:9600   2:19200   3:38400   4:57600   5:115200
        // BaudStr: for exapmle "19200"
        // ComName: for example "COM48"
        // connect: 0, 1

    bool dc_closeSerial(void) const override;

    bool dc_isPortOpen(void) const override ;

    void dc_autoRequest(bool on) const override ;
        // select if READ-Requests are sent manually one by one or automatically
        // automatically request ALL digital and analog sensors, get time/date, get status information

    bool dc_updateDC(QString binFileName, QString baudrate,
                     QString comPort) const override;
    
    bool dc_updatePrinterTemplate(enum FileTypeJson type,
                                  QVector<int> templateIdx,
                                  QVector<QString> fnames,
                                  QString br,
                                  QString serial = QString()) const override;

    bool dc_printTemplate(enum FileTypeJson type,
                          QVector<int> templateIdx,
                          QString br,
                          QString serial = QString()) const override;
    // ------------------------------------------------------------------------------
    // 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 dc_requTestResponse() const override;
        // tell DC2 to return his TestString in order
        //   to test the serial and the baudrate
        // must always be triggered manually, is never sent automatically

    bool dc_readAnswTestResponse() const override;
        // retval: true: test was successful, got right response

    uint8_t dc_isRequestDone(void) const override;
        // retval:  0: request is still in progress
        //          1: answer from DC2 was OK
        //          2: wrong answer from DC2

    uint16_t dc_getCompletePayLoad(uint16_t plBufSiz, uint8_t *payLoad) const override;
        // 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

    void dc_setWakeFrequency(uint8_t period) const override;
        // RTC wakes DC2 (and PTU) by hardware signal every 32seconds
        // change wake signal period to 1...64s

    void dc_OrderToReset(void) const override;
        // want DC2 to reset (in order to start Bootloader)

    QString dc_getSerialState(void) const override;
    void dc_clrSerialStateText(void) const override;

    void bl_sendDataDirectly(uint8_t length, uint8_t *buf) const override;
        // send without protocol frame, needed for the DC bootloader

    uint8_t getRawRecLength(void) const override;

    uint8_t getRawReceivedData(uint8_t *receivedData) const override;

    QString dc_getSerialParams(void) const override;

    QString dc_getHWversion(void) const override;

    QString dc_getSWversion(void) const override;

    QString dc_getState(void) const override;

    QString dc_getTxt4RsDiagWin(void) const override;
    void dc_clrTxt4RsDiagWin(void) const override;
    QString dc_get2ndTxt4RsDiagWin(void) const override;
    void dc_clr2ndTxt4RsDiagWin(void) const override;
    QString dc_getTxt4HsStateLine(void) const override;
    void dc_clrTxt4HsStateLine(void) const override;
    QString dc_getTxt4masterStateLine(void) const override;
    void dc_clrTxt4masterStateLine(void) const override;
    QString dc_getTxt4resultStateLine(void) const override;
    void dc_clrTxt4resultStateLine(void) const override;
    QString dc_getdataStateLine(void) const override;
    void dc_clrTxt4dataStateLine(void) const override;
    QString dc_getdatifLine(void) const override;
    void dc_clrTxt4datifLine(void) const override;

    // using DC2 Bootloader
    void bl_iniChain(void) const override;
    bool bl_importBinFile(QByteArray readBinFile, uint32_t fileSize, char withDispl) const override;
    uint8_t bl_activatBootloader(uint8_t *sendData) const override;
    uint8_t bl_startChain(void) const override;
    uint8_t bl_readBLversion(uint8_t *sendData) const override;
        // minimum size of sendData-buffer: 5byte  retval: length
    uint8_t bl_readFWversion(uint8_t *sendData) const override;
        // minimum size of sendData-buffer: 5byte  retval: length

    uint8_t bl_prepareDC_BLcmd(uint8_t Cmd, uint8_t SendDataLength, uint8_t *sendData, uint8_t *outBuf) const override;
        // 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

    uint8_t bl_exitBL(uint8_t *sendData) const override;
        // minimum size of sendData-buffer: 5byte  retval: length

    // ------------------------------------------------------------------------------
    // 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
/*
    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;
    };
*/
    uint8_t rtc_getDateTime(struct Trtc_DateTime *rtc_DateTime) const override;

    uint8_t rtc_setDateTime(void) const override;
        // synch DC2 with PC or PTU system time and date

    void rtc_getTime(uint8_t *hh, uint8_t *mm, uint8_t *ss) const override;
        // get time directly

    void rtc_getDate(uint8_t *yy, uint8_t *mm, uint8_t *dd) const override;
        // get date directly

    uint8_t rtc_getToday(uint8_t *dow, uint16_t *minOfToday, uint32_t *secOfToday) const override;
        // dow=day of week, 1=monday...7
        // minOfToday: 0=midnight...1439= 23:59
        // secOfToday: 0=midnight...86399= 23:59:59

    bool rtc_isLeapYear(uint8_t *lastLeapYear, uint8_t *NextLeapYear) const override;
        // retval true: this year is leap year

    bool rtc_isLeapYear() const override;

    void rtc_getWeek(uint8_t *DayOfWeek, uint8_t *HoursOfWeek, uint16_t *MinutesOfWeek) const override;
        // DayOfWeek: 1=monday...7
        // HoursOfWeek: 0=Monday 0:00 o'clock...167=Sunday 23:00
        // MinutesOfWeek: 0=Monday 0:00 o'clock...10079=Sunday 23:59

    void rtc_getMonth(uint8_t *DayOfMonth, uint16_t *HoursOfMonth, uint16_t *MinutesOfMonth) const override;
        // DayOfMonth: 1...31
        // HoursOfMonth: 0 = 0:00o'clock of 1.day in month     up to 743
        // MinutesOfMonth:0 = 0:00o'clock of 1.day in month     up to 44639

    void rtc_getYear(uint16_t *DayOfYear, uint16_t *HoursOfYear, uint32_t *MinutesOfYear) const override;
        // DayOfYear: 1...366  1= 1.Jan of this current year
        // HoursOfYear: 0=1.Jan 0:00o'clock ...8783=31.12 23 o'clock
        // MinutesOfYear: 0=1.Jan 0:00o'clock ...527039=31.12 23:59 o'clock

    QString rtc_getTimStr(void) const override;
    QString rtc_getDatStr(void) const override;
    QString rtc_getTimDatStr(void) const override;

    // UID
    void     dc_getUID8byte(uint8_t *buf8byteUid) const override;
    QString  dc_getUIDstr() const override;
    uint64_t dc_getUIDnumber(void) const override;


    // Analog inputs:
    uint32_t dc_getTemperature(void) const override;       // in Sax-Format 0...400 (0=-50,0°C    100=0,0°C    141=20,5°C    400=150,0°C)
    QString  dc_getTemperaturStr(void) const override;

    uint32_t dc_getVoltage(void) const override;           // in mV,  0...65,535V
    QString  dc_getVoltagStr(void) const override;

    bool dc_mainFuseIsOk(void) const override;

    // ------------------------------------------------------------------------------
    // Level 3: digital outputs and simple switching of connected devices
    //          simple processes like flashing a led or open flap for 1s
    // ------------------------------------------------------------------------------

    void lock_switchContactPower(bool on) const override;

    // Locks move until stop cmd (0)
    uint8_t lock_switchUpperLock(uint8_t dir) const override;
        // dir 0=off 1=up 2=down
    uint8_t lock_switchLowerLock(uint8_t dir) const override;
        // dir 0=off 1=up 2=down
    void lock_switchVaultDoor(void) const override;

    void coin_switchRejectMotor(uint8_t dir) const override;

    void coin_rejectCoins(void) const override;

    // LEDs
    void led_switchLedIllumination(uint8_t on) const override;
    void led_switchLedService(uint8_t on) const override;
    void led_switchLedPaper(uint8_t on, uint8_t ton, uint8_t tof) const override;
    void led_switchLedPinPad(uint8_t on, uint8_t ton, uint8_t tof) const override;
    void led_switchLedStart(uint8_t on, uint8_t ton, uint8_t tof) const override;
    void led_switchLedCoinbassin(uint8_t on, uint8_t ton, uint8_t tof) const override;

    void fan_switchFan(bool on) const override;
    void alarm_switchSiren(bool on) const override;
    void bar_OpenBarrier(bool open) const override;
    void ptu_switchWake(bool WAKEACTIVE) const override;

    void prn_switchPower(bool on) const override;

    void mif_readerOn(bool on) const override;
    void shut_move(bool open) const override;
    void esc_moveFlaps(uint8_t flap ) const override;
        // 0: close both  1: open take-flap   2: open return

    void mdb_switchPower(bool on) const override;
    void mdb_switchWake(bool WAKEACTIVE) const override;

    void mod_switchPower(bool on) const override;
    void credit_switchPower(bool on) const override;

    void aux_power(bool on) const override;
    void aux_setUsage(uint8_t PinDirection) const override;
    void aux_setOutputs(uint8_t PinIsHigh) const override;


    void mod_switchWake(bool WAKEACTIVE) const override;

    void credit_switchWake(bool WAKEACTIVE) const override;




    // ------------------------------------------------------------------------------
    // Level 3: digital inputs of connected devices
    // ------------------------------------------------------------------------------

    bool door_isContactPowerOn(void) const override;

    uint8_t door_getSwitches(void) const override;
        // retval:  bit0: upper door  1: low door  2:vault door

    bool    door_isUpperDoorOpen(void) const override;

    bool    door_isLowerDoorOpen(void) const override;

    bool    vault_isVaultDoorOpen(void) const override;

    uint8_t vault_getSwitches(void) const override;
        // retval bit0: cash box,  bit 1: bill box

    bool    vault_isCoinVaultIn(void) const override;

    bool    vault_isBillVaultIn(void) const override;

    uint8_t door_getLocks(void) const override;
        // retval bit0: upper lever is up
        //        bit1: upper lever is down
        //        bit2: lower lever is up
        //        bit3: lower lever is down

    bool door_upperDoorIsLocked(void) const override;

    bool door_upperDoorIsUnlocked(void) const override;

    bool door_lowerDoorIsLocked(void) const override;

    bool door_lowerDoorIsUnlocked(void) const override;

    bool bar_optoIn1isOn(void) const override;

    bool bar_optoIn2isOn(void) const override;

    bool ptu_WakeINisActive(void) const override;

    bool prn_isPrinterPowerOn(void) const override;
    uint8_t prn_PrnFuseIsOk(void) const override;
    //retval:  0: fuse blown   1: fuse OK   2:unknown as printer power is off

    bool prn_readyINisActive(void) const override;

    bool mif_cardIsAttached(void) const override;
    bool mif_isMifarePowerOn(void) const override;

    bool mdb_WakeINisActive(void) const override;
    bool mdb_testIsmdbTxDon(void) const override;
    bool mdb_isMdbPowerOn(void) const override;

    bool coid_isAttached(void) const override;
    bool coin_escrowIsOpen(void) const override;

    bool aux_isAuxPowerOn(void) const override;

    uint8_t aux_getAuxInputs(void) const override;

    bool mod_isGsmPowerOn(void) const override;

    bool cred_isCreditPowerOn(void) const override;

    bool cash_getRejectMotorHomePos(void) const override;

    uint8_t cash_getLowPaperSensor(void) const override;
        // 0: Sensor sees paper 1: no paper 99: off


    // ------------------------------------------------------------------------------
    // Level1,2,3     RD request commands
    // ------------------------------------------------------------------------------

    // all read-requests can be sent manually by the following functions
    //   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,
    //    but it's allowed to send them in order to speed up the refreshing of the inputs

    void request_DC2serialConfig() const override;
    void request_DC2_HWversion() const override;
    void request_DC2_SWversion() const override;
    void request_DC2_condition() const override;
    void request_DC2_UID() const override;
    void request_DC2_TimeAndDate() const override;
    void request_DC2_analogues() const override;
    void request_DC2_digitalInputs() const override;
    void request_DC2_digitalOutputs() const override;

    // ------------------------------------------------------------------------------
    // the folowing device state requests are deploed only if device is powered up:
    void request_PrinterHwState() const override;
    void request_PrinterCurrentFonts() const override;
    void request_PrinterStateComplete() const override;

    void request_MifareReaderState() const override;
    void request_MifareCardType() const override;
    void request_MifareAtbType() const override;
    void request_MifareID() const override;
    void request_MifareData(uint8_t dataBlockNumber) const override;
        // dataBlockNumber must be 0....11, returns 64byte of data

    void request_MDB_Status() const override;
    void request_MDB_lastResponse() const override;
    void request_EMP_allParameters() const override;
    void request_EMP_lastCoin() const override;



    // ------------------------------------------------------------------------------
    // 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 test_getDO_mdbRXtst(void) const override;

    uint8_t lock_getDO_motors(void) const override;
        // bit0: upper lock forward    bit 1 backward
        // bit2: lower lock forward    bit 3 backward

    uint8_t test_serialState(void) const override;
        // test on-board signals for the serials
        // serial drv on/off, Serial mux1, Serial mux2
    bool test_serialIsOn(void) const override;
    bool test_serialMux1isSetToPrinter(void) const override;
    bool test_serialMux1isSetToModem(void) const override;
    bool test_serialMux2isSetToCredit(void) const override;
    bool test_serialMux2isSetToMifare(void) const override;

    bool led_coinIsOn(void) const override;
    bool led_frontIsOn(void) const override;
    bool led_ticketIsOn(void) const override;
    bool led_pinIsOn(void) const override;
    bool led_StartIsOn(void) const override;
    bool led_insideIsOn(void) const override;

    bool fan_isOn(void) const override;
    bool siren_isOn(void) const override;
    bool bar_relayIsOn(void) const override;
    bool ptu_WakeOutIsOn(void) const override;

    bool aux_powerIsOn(void) const override;

    bool coin_shutterIsOpen(void) const override;
    bool coin_shutterTestOutput(void) const override;

    uint8_t coin_escrowFlapOpened(void) const override;
        // retval: 1:return flap is open   2:take flap is open    0:closed



    // ------------------------------------------------------------------------------
    // Level4 ( Timer processes, device supervision by DC, processes with more then one devices
    // WRITE
    // ------------------------------------------------------------------------------


    void sendDeviceSettings(uint8_t kindOfPrinter,      uint8_t kindOfCoinChecker,
                            uint8_t kindOfMifareReader, uint8_t suppressSleep,
                            uint8_t kindOfModem,        uint8_t kindOfCredit        ) const override;
    // enable hardware in device controller:
    // kindOfPrinter:       0:off 1: GPT4672 (only this one implemented)
    // kindOfCoinChecker:   0:off 1:EMP820 2:EMP900 3: C²_changer
    // kindOfMifareReader:  0:off 1: SL025   (only this one implemented)
    // suppressSleep:       0:sleep allowed 1: sleep surpressed for special reason
    // kindOfModem:         0:off 1: ATB_Sunlink_LTE        (not yet implemented)
    // kindOfCredit:        0:off 1:  cVendTopp  2:cVendPin (not yet implemented)

    void request_ReadbackDeviceSettings() const override;

    void readback_DeviceSettings(uint8_t *length, uint8_t *data) const override;
        // refer to DC2 manual for exact content
        // state 5.5.21: byte[0]=kindOfPrinter   byte[1]=kindOfCoinChecker
    //               byte[2]=kindOfMifarereadr   byte[3]=suppress sleep mode
    //               byte[4]=kindOfModem         byte[5]=kind of cc terminal

    uint8_t emp_returnLastCoin(uint16_t *value, uint8_t *signal) const override;
        // use for changer

    void sendMachineID(uint16_t customerNr, uint16_t machineNr,
                              uint16_t borough, uint16_t zone,
                              uint16_t alias,   char *location) const override;

    void request_ReadbackMachineID() const override;

    void readback_machineIDdata(uint8_t *length, uint8_t *data) const override;
    // state 5.5.21: byte[0,1]=customer number    byte[2,3]=machine number
    //               byte[4,5]=borough   byte[6,7]=zone   byte[8,9]=alias name
    //               byte[10...41]=location


    // Locks stops automatically at end switch or by timeout
    uint8_t lock_openUpperDoor(void) const override;
    uint8_t lock_closeUpperDoor(void) const override;

    uint8_t lock_openLowerDoor(void) const override;
    uint8_t lock_closeLowerDoor(void) const override;


    void shut_openOnce(void) const override;
        // and close automatic after shutter time

    void shut_openForCoin(bool start) const override;
        // open flap if coin is attached
        // once process is started it runs until stop command

    void shut_sendOpeningTime(uint16_t timeIn_ms ) const override;
        // after this time without retrigger the flap is closed

    void esc_takeMoney(void) const override;
        // and close automatically after escrow time (1s)

    void esc_returnMoney(void) const override;
        // and close automatically after escrow time (1s)

    void mif_creatAtbCard(uint8_t cardType) const override;


    // ------------------------------------------------------------------------------
    // read response from DC2 (input data)
    // ------------------------------------------------------------------------------

    uint8_t mif_returnReaderStateAndCardType(uint8_t *buf, uint8_t maxBufferSize) const override;
        // 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 preent (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)
    */

    bool mif_readerIsOK(void) const override;

    bool mif_cardAttached(void) const override;

    uint8_t mif_readResult(void) const override;
        // result: 0: unknown or still in progress
        //         1: card read successful
        //         2: reading error

    QString mif_cardUID(void) const override;

    uint8_t mif_getCardDataDec(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize) const override;

    QString mif_getCardDataStr(uint8_t blockNumber) const override;
        // with blockNumber=0...11




    // ----------------------------------------------------------------------------------------------------------
    // --------------------------------------------- PRINTER ----------------------------------------------------
    // ----------------------------------------------------------------------------------------------------------

    // read printer condition and settings

    uint8_t prn_getHwState(struct Tprn_hw_state *prn_hw_state) const override;
        // retval: status byte
            // 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
        // and return struct "Tprn_hw_state"

    bool prn_isUpAndReady(void) const override;
        // true: printer is powered, serial is ok, no error, printer is connected and resonding

    void prn_getCurrentFontSetting(struct Tprn_currentSettings *prn_fonts) const override;


    // send Commands to printer:

    void prn_sendText(QByteArray *buf) const override;
        // up to 1280 bytes

    void prn_sendPrnSysCmd(uint8_t para1, uint8_t para2, uint32_t para3) const override;
        // send three byte through to printer, see printers manual

    void prn_sendPrnEscCmd(uint8_t para1, uint8_t para2, uint8_t para3, uint8_t para4) const override;
        // send four byte through to printer, see printers manual


    void prn_sendPrnSetup(uint16_t paperSpeed, uint8_t density,  uint8_t alignment, uint8_t orientation) const override;
        // 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

    void prn_movePaper(uint8_t wayInMm, uint8_t direction) const override;
        //direction: 1=forward 2=backward
        //
    void prn_setFonts(uint8_t font, uint8_t size, uint8_t width, uint8_t height) const override;
        // font = kind of font 5...11 (0..22)
        // 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

    void prn_setLetters(uint8_t bold, uint8_t invers, uint8_t underlined) const override;
        // bold: 0/1
        // invers: 0/1
        // underlined: 0/1

    void prn_cut(uint8_t kindof) const override;
        // kindof: 1=full cut 2=partial cut 3=eject (5xLF + full cut)

    void prn_newLine(uint8_t nrOfLines) const override;

    void prn_printCompleteFontTable(void) const override;


    void prn_printBarcode(uint8_t kindOf, uint8_t withText,  uint8_t offset, uint8_t rotation, uint8_t dataLeng, uint8_t *data) const override;
        // kind of barcode: 0=Code39   1=Code128   2=EAN13    3= 2/5interleaved    4=UPC-A   5=EAN8
        // withText:    print readable text below
        // offset: move by pixel from left border
        // rotation
        // dataLeng in byte

    void prn_sendQRdata(QByteArray *buf) const override;
        // maximal 150 alphanummeric bytes

    void prn_printQRcode(void) const override;
        // QRcode may have 1...150 alphanummeric data, must be transfered in advance


    void prn_printLogo(uint8_t nrOfLogo, uint8_t offset ) const override;
        // nrOfLogo: 1..4 in flash  5...8 in Ram
        // offset: in mm form left border



    // .........................................................
    // Parking Ticket (print-out document) designer TD
    // .........................................................

    // Predefine document Layout (e.g. parking ticket) in advance and stroe it for quick and easy use
    // in opposite to the above "single" commands you need only one or a few commands at vending time.
    // Stored text is just send to printer once the printing command is issued
    // stored commands within the text are interpreted and executed right at the place (in ticket) they are
    // example: start bold, <text in bold>, stop bold
    // Predefinition of up to 16 ticket Layouts is possible, 0...1280 byte each
    // Number 0..15, al keept non-volatile
    // up to 8 dynamic values can be defined in the template ("print val3 here") and will be sent with printing command
    // example: print current time at this point (the time of printing not the storage time!!)

    void pri_startTicketDesign(void) const override;
        // start for every new printer document, reseting collecting buffer

    // all further functions write/append text, numbers and command to the ticket-buffer, up to 1278 bytes allowed
    // return val of the appending functions: true=ok false=too long, buffer full

    int pri_TD_getCurrentSize(void) const override;
        // retval: 0...1278

    bool pri_TD_addText(QByteArray text) const override;
        // example: pri_TD_addText("Hello") const override;
        // example: pri_TD_addText(tempStr) const override;
        // retval: true=ok false=too long, buffer full

    bool pri_TD_addValue(int val) const override;
        // +/- 0...2^(31)

    bool pri_TD_addNewLine(void) const override;

    bool pri_TD_addSign(char sign) const override;
        // example: '.'   ' '   0x20 'W' '$'

    bool pri_TD_addCommand(char group, char attribute, char p1, char p2, char p3, char p4, char p5) const override;
        // 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: 0...8
                attribute 11 : font size
                      p1: 6...20
                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 :
                        p1: 1...8 = print dynData 0..7 at this place

    */

    char prn_clearDocument(uint8_t documentNumber) const override;
        // clear memory buffer for ONE document
        // function takes a second! don't send right before "store doc"

    bool prn_store_Document(uint8_t documentNumber ) const override;

        // send the predefined Layout (generated with above TD functions) to DeviceController to save
        // documentNumber=0...15
        // maximal 1280 bytes each
        // allowed: 0x20...0xFF, 0x0A, 0x0C, 0x1B (LF, CR, Esc)
        // 0x1B=start of embedded command (next 7bytes = command)

    // with a print command a set of 8 dynamic strings can be sent
    // the place in the ticket layout is predefined (already in DC memory)
    // the dynamics are first calculated at printing time

    bool prn_printDocument(uint8_t documentNumber, struct T_dynDat *dynTicketData) const override;





    // ----------------------------------------------------------------------------------------------------------
    // --------------------------------------------- MDB Bus ----------------------------------------------------
    // ----------------------------------------------------------------------------------------------------------

    //void mdb_switchPower(bool on) const override;            defined above
    //void mdb_switchWake(bool WAKEACTIVE) const override;     defined above
//    bool mdb_WakeINisActive(void) const override;
//    bool mdb_testIsmdbTxDon(void) const override;
//    bool mdb_isMdbPowerOn(void) const override;
//    void request_MDB_Status() const override;
//    void request_MDB_lastResponse() const override;


    void mdb_sendBusReset(void) const override;

    void mdb_sendCommand(uint8_t toMdbDevice, uint8_t mdbCommand) const override;
        // send one bus command directly over mdb bus, refer to mdb manual for commands
        // this command is not needed in normal operation, just for new or special things

    void mdb_sendMessage(uint8_t toMdbDevice, uint8_t mdbCommand, uint8_t nrOfData, uint8_t *dataBuffer) const override;
        // nrOfData = sizeOf(dataBuffer) maximal 34 byte according mdb specs
        // same as mdb_sendCommand, just with data

    bool mdb_busIsReadyToWork() const override;

    bool mdb_deviceVoltageOK() const override;

    bool mdb_busVoltageOk() const override;

    uint8_t mdb_getLastDeviceResponse(uint8_t *fromDevice, uint8_t *lastRequest,
                                      uint8_t *responseLength, uint8_t *responseBuffer) const override;
        // 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)





    // ----------------------------------------------------------------------------------------------------------
    // ---------------------------------- Electronic Coin Validator EMP -----------------------------------------
    // ----------------------------------------------------------------------------------------------------------


    void emp_sendSettings(uint16_t coinAcceptance, uint8_t tokenChannel, uint16_t *coinDenomination ) const override;
        // 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...)

    void emp_pollingOnOff(uint8_t on) const override;

    void emp_startCoinAcceptance(void) const override;

    void emp_stopCoinAcceptance(void) const override;

    void emp_getAllParameters(struct T_emp *emp) const override;
        // see struct in hwapi.h
        // usage example:
        //      hwapi   *HWaccess const override;
        //      HWaccess = new hwapi() const override;
        //      struct T_emp   myEmp const override;
        //      HWaccess->emp_getAllParameters(&myEmp) const override;
        //          readval=myEmp.pollingRunning const override;

    uint8_t emp_chkIfCoinInserted(void) const override;
        // retval: 0...16 coins left in FIFO

    void emp_getNewCoinRecord(uint8_t *valid, uint8_t *signal, uint8_t *error, uint16_t *value) const override;
        // with every call ONE coin is taken out of FIFO and pointer decremented
        // valid: should be 1
        // signal: comes right from coin checker, 0...15 (0=first programmed coin type) 0xFF=no signal
        // error: was reported from EMP as dynamic signal right after coin insertion (instead of
        //          coin signal), example: 3=unknown coin  4=coin is blocked by host.  0xFF=no error
        // value: of the coin. Depends on parameter "coinDenomination" in function "emp_sendSettings"
        //          if coinDenomination[coin 0..15] = 0 then the value programmed in coin checker is taken
        //          if coinDenomination > 0 then this value is taken.
        //          Useful in case of two currencies (adapt to local currency) or for token.

    // function gives more details as "emp getLastCoin()" but "emp getLastCoin()" is easier to use

    // alternativ to emp_getNewCoinRecord( ):
    uint8_t emp_giveLastCoin(uint16_t *value, uint8_t *signal) const override;
        // 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
        //          0xFF means NO error or NO signal  (as 0 is a valid error/signal)
        // signal: channel nr reported from checker 0...15





// neu, 25.3.23

    void bl_rebootDC(void) const override;

    void bl_startBL(void) const override;
    bool bl_checkBL(void) const override;
    bool bl_isUp(void) const override;
        // return true is bl is up and running
        // also initializes "sendFile"

    void bl_sendAddress(uint16_t blockNumber) const override;
        // 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

    uint8_t bl_wasSendingAddOK(void) const override;
    // return val: 0: no response by now  1:error  10: OK

    void bl_openBinary(void) const override;

    void bl_sendDataBlock(uint8_t length, uint8_t *buffer) const override;
    // send 64 byte from bin file

    void bl_sendLastBlock(void) const override;

    uint8_t bl_wasSendingDataOK(void) const override;
    // return val: 0: no response by now  1:error  10: OK

    void bl_stopBL(void) const override;


    // Bootlader, not used or obsolete
    //bool bl_isDiagAvailable(void) const override;
    //QString dc_getDiagText(void) const override;
    //void bl_startSending(void) const override;
    //void bl_sendFile(void) const override;



// neu, ab 6.4.23
// bereits vorhanden, nochmal getestet/verbessert:
    // void led_switchLedPaper(uint8_t on, uint8_t ton, uint8_t tof) const override;
    // void alarm_switchSiren(bool on) const override;

    // void mif_readerOn(bool on) const override;
    // bool mif_cardIsAttached(void) const override;

    // void shut_move(bool open) const override;
    // void esc_moveFlaps(uint8_t flap ) const override;
        // 0: close both  1: open take-flap   2: open return
    // void shut_openOnce(void) const override;
        // and close automatic after shutter time
    // void shut_openForCoin(bool start) const override;
        // open flap if coin is attached
        // once process is started it runs until stop command
    // void shut_sendOpeningTime(uint16_t timeIn_ms ) const override;
        // after this time without retrigger the flap is closed
    // void esc_takeMoney(void) const override;
        // and close automatically after escrow time (1s)
    // void esc_returnMoney(void) const override;
        // and close automatically after escrow time (1s)

    // void prn_switchPower(bool on) const override;
    // void prn_sendText(QByteArray *buf) const override;
        // up to 1280 bytes

    // uint8_t rtc_setDateTime(void) const override;
            // send system time

    //void sendDeviceSettings(uint8_t kindOfPrinter,      uint8_t kindOfCoinChecker,
    //                        uint8_t kindOfMifareReader, uint8_t suppressSleep,
    //                        uint8_t kindOfModem,        uint8_t kindOfCredit        ) const override;

    //void sendMachineID(uint16_t customerNr, uint16_t machineNr,
    //                          uint16_t borough, uint16_t zone,
    //                          uint16_t alias,   char *location) const override;


    bool rtc_setTimeDateDirect(struct Trtc_DateTime *DateTime) const override;
        // return true if successful. could fail if more the 8 commands are waiting

    bool rtc_getExtendedTime(uint8_t *leng, uint8_t *data) const override;
    bool rtc_getExtendedTime(struct T_extTime *exTime) const override;

    bool sys_runCompleteTest(void) const override;
        // warning: lasts 20s in one pace

    bool sys_ready4sending(void) const override;
    // return true if a Json-file can be sent

    bool sys_sendJsonFileToDc(uint8_t kindOfFile, uint8_t nrOfTemplate, uint8_t *content ) const override;
        // 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

    bool prn_sendDynamicPrnValues(uint8_t *dynPrnVal ) const override;
    // 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

    bool prn_printTemplate(uint8_t nrOftemplate) const override;
        // print one of the templates loaded by Json prior
        // nr = 1..32
        // return true if sending, false if cmd-stack is full

    void log_getHoldAccountNumbers(uint8_t *nrOfVals, uint16_t *accNr ) const override;
    // returns all acc nrs of the backuped vault records
    // use: uint16_t backupedAccNumbers[8]

    bool log_selectVaultRecord(uint16_t accountNr ) const override;
        // return true if sending, false if cmd-stack is full
        // and trigger transfer

    bool log_chkIfVaultRecordAvailable(void) const override;
        // return true if completly received

    bool log_getVaultRecord(struct T_vaultRecord *retVR) const override;
        // which was selected by: log_selectVaultRecord()
        // to be forwarded to Ismas

    bool prn_printAccountReceipt(void) const override;
        // return true if sending to DC OK, false if cmd-stack is full

    bool prn_printTestTicket(void) const override;
        // return true if sending to DC OK, false if cmd-stack is full

    bool cash_startPayment(uint32_t amount) const override;
        // 17.4.23TS: extended to 32bit

    bool cash_cancelPayment(void) const override;
        // and return coins

    bool cash_stopPayment(void) const override;
        // and keep coins in escrow

    uint32_t getInsertedAmount(void) const override;

    uint16_t getLastInsertedCoin(void) const override;

    bool getAllInsertedCoins(uint16_t *types, uint16_t *values) const override;
        // alle bei diesem Verkauf eingeworfenen Münzen sind gespeichert, max 64


    // after ticket/goods issue:
    bool vend_success(void) const override;
        // conclude payment process, encash all inserted coins to vault. Printing was successful
        // if possible return change

    bool vend_failed(void) const override;
        // conclude payment process and return all inserted coins





    uint8_t mif_getCardType(QString *cardholder) const override;
        // return 1,2,3,4 = upper, lower access card, printer test, coin test
        // cardholder: 7byte Name-String

    uint64_t sys_getWakeSource(void) const override;
        // retval: 6 bytes, bit coded, 1=event keeps DC awake

    uint8_t sys_getWakeReason(void) const override;
         // 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

    void sys_getDeviceConditions(uint8_t *leng, uint8_t *data) const override;

    void sys_getDeviceConditions(struct T_moduleCondition *devCond) const override;

    void sys_getDynMachineConditions(uint8_t *leng, uint8_t *data) const override;
    void sys_getDynMachineConditions(struct T_dynamicCondition *dynMachCond) const override;


    uint32_t cash_getAmountInVault(void) const override;

    uint16_t cash_getNrCoinsInVault(void) const override;

    uint8_t prn_getPrintResult() const override;

    uint8_t prn_getCurrentPrinterState() const override;
        //        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

    void sys_sendDeviceParameter(struct T_devices *deviceSettings) const override;

    void sys_restoreDeviceParameter(struct T_devices *deviceSettings) const override;


    /* ---------------------------------------------------------------------------------------------
    // ------------   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 sys_componentAssessment(void) const override;
    // this function decides if vending mode is possible, independant from door
    // return >0 in case of error
    // is inncluded in sys_superviseSystem

    uint8_t sys_superviseSystem(void) const override;
    // this function proofs if vending is possible depending of doors state


    uint8_t sys_getSystemErrors(void) const override;

    // ---------------------------------------------------------------------------------------------
    // ---------------------------------------------------------------------------------------------
    // ---------------------------------------------------------------------------------------------

signals:
    void hwapi_templatePrintFinished_OK(void) const override;
    void hwapi_templatePrintFinished_Err(void) const override;
    void hwapi_gotNewCoin(void) const override;
    void hwapi_vendStopByMax(void) const override;
    void hwapi_vendStopByPushbutton(void) const override;

 private slots:
    void hwapi_slotPrintFinished_OK(void);
    void hwapi_slotPrintFinished_Err(void);
    void hwapi_slotGotCoin(void);

};


#endif



/*
    // Coin checker and changer mdb4.2 / section 5
    // Level 2 Commands  (predefined device msg acc. mdb manual and auto-poll)
    uint8_t mdb_coin_startPolling(bool on) const override;    // send ether one command (from list below)
                                               // or a poll command in the proper polling grid (e.g. every 100ms)
    uint8_t mdb_coin_reset() const override;
    uint8_t mdb_coin_setup() const override;
    uint8_t mdb_coin_tubestatus() const override;
    uint8_t mdb_coin_pollManually(void) const override;
    uint8_t mdb_coin_type(uint16_t coinEnable, uint16_t dispenseEnable) const override;
    uint8_t mdb_coin_dispense(uint8_t disp) const override;
    uint8_t mdb_coin_expansion(uint8_t subCmd, uint8_t send[32]) const override;
    uint8_t mdb_coin_getResponse(void) const override;
            // 0: no response    1: got ACK    2: got NAK    3 got ACK with additional data
    uint8_t mdb_coin_getDataLen(void) const override;
        // return nr of byte received from any mdb device
    uint8_t mdb_coin_getData(uint8_t *mdb_data, uint8_t maxBufferSize) const override;



    // Bill validator       // section 6
    uint8_t mdb_bill_startPolling(bool on) const override;
    uint8_t mdb_bill_reset() const override;
    uint8_t mdb_bill_setup() const override;
    uint8_t mdb_bill_security(uint16_t secLevel) const override;
    uint8_t mdb_bill_pollManually(void) const override;
    uint8_t mdb_bill_billType(uint16_t billEnable, uint16_t escrowEnable) const override;
    uint8_t mdb_bill_escrow(uint8_t action) const override;
    uint16_t mdb_bill_stacker(void) const override;
    uint8_t mdb_bill_expansion(uint8_t subCmd, uint8_t send[32]) const override;
    uint8_t mdb_bill_gotPollResponse(void) const override;
            // 0: no response    1: got ACK    2: got NAK    3 got ACK with additional data
    uint8_t mdb_bill_getDataLen(void) const override;
    uint8_t mdb_bill_getPollData(uint8_t *mdb_data, uint8_t maxBufferSize) const override;



    // Level 3 Commands - all cash devices are used together and automatically
    // -->easiest way to use

    // setting up payment:
    uint8_t cash_getAcceptance(struct Tcash_state *cash_state) const override;
        // return device specific parameters, (e.g. which tubes are installed)
        // to be requested before/after payment
    uint8_t cash_setMaxReturn(uint32_t amount) const override;         // Security Limit
    uint8_t cash_setMaxAcceptance(uint32_t amount) const override;     // can pay up to this amount
        // example: set to 12€ (=max price step), then the 3rd 5€ bill would be kept in escrow
        // or with coins: max. insertable = 13,95€ (11,95€ is still <12€, plus a 2€-coin)
    uint8_t cash_setCoinsToBeAccepted(uint16_t coinVal[2][16]) const override;
        // up to 16 coins per currency in one or two currencies
        // [0]=first currency, e.g. Huf  [1]=2nd, like euros
    uint8_t cash_setBillsToBeAccepted(uint32_t billVal[2][16]) const override;
    uint8_t cash_setOpeningTime(uint16_t opentime_100ms) const override;       // coin slot is opening/closing automatically
    uint8_t cash_setWaitForLastCoinTime(uint16_t lastCoinTime_100ms) const override;
        // while this time coin/bill aceptance is still active after "disable payment" command
    uint8_t cash_getAllsettings(struct TcashSettings cashSettings) const override;
        // return all above set own parameters

    // starting payment
    uint8_t cash_powerUp(bool on) const override;              // power up/down devices (bill takes up to 3s)
    uint8_t cash_enablePayment(bool start) const override;     // start/stop accepting bills and coins

    // running payment
    bool    gotNewCoinBill(void) const override;                    // true on every insertion, only once
    uint8_t cash_getInserted(struct Tcash_pay *payment_state) const override;

    // finishing payment
    uint8_t cash_coinEscrowTake(void) const override;
    uint8_t cash_coinEscrowReturn(void) const override;
    uint8_t cash_return(uint32_t amount) const override;
*/


/*
    uint8_t cc_setCondition(uint16_t chgCmd) const override;      // e.g. change to state registered, sleep, open, off....
    uint16_t cc_getCondition(void) const override;                // e.g. now socket open
    bool    cc_sendBufferFree(void) const override;               // sending allowed (before writing) and sending finished (after writing)
    uint8_t cc_sendDataBlk(uint16_t len, uint8_t *buf) const override;
    void    cc_wantReadData(uint16_t nrOfData) const override;                        // start reading
    uint16_t cc_gotData(void) const override;                             // return nr of received bytes
    uint8_t cc_loadDataBlk(uint16_t len, uint8_t *buf) const override;
    uint8_t cc_getWorkFlow(void) const override;
        // off, activated, gotStart_wait4card, wait4pin, gotPin, callingBank, CardAccepted.....
    uint8_t cc_setupSerial(struct TserialParams serialParameter) const override;
    uint8_t cc_getCurrentSerialSettings(struct TserialParams *serialParameter) const override;
*/


/*

struct TcashSettings
{
    uint32_t MaxReturnAmount const override;
    uint32_t MaxAcceptAmount const override;
    uint32_t CoinsAcceptedCur[2][16] const override;
    uint32_t BillsAcceptedCur[2][16] const override;
    uint32_t availableReturnAmount const override;

} const override;


struct Tcc_hw_state
{
    bool powerRdBk const override;     // prn pwr is on
    bool rsSwOk const override;        // serial switch (printer or modem) is set to CreditCard (iUC)
    bool rsDrvOk const override;       // RS232 converter for PTU, Printer and Modem in on
    uint8_t HwState const override;    // idle, off, on, ready
    bool gotAnswer const override;     // cable OK?
    uint8_t moduleType const override;
    uint8_t protocolType const override;

} const override;


*/


/*
    // not yet implemented
    uint8_t mod_power(bool on) const override;
    uint8_t mod_getHwState(struct Tmod_hw_state *mod_hw_state) const override;
    uint8_t mod_setCondition(uint16_t chgCmd) const override;      // e.g. change to state registered, sleep, open, off....
    uint16_t mod_getCondition(void) const override;                // e.g. now socket open
    bool    mod_sendBufferFree(void) const override;               // sending allowed (before writing) and sending finished (after writing)
    uint8_t mod_sendDataBlk(uint16_t len, uint8_t *buf) const override;
    void    mod_wantReadData(uint16_t nrOfData) const override;                        // start reading
    uint16_t mod_gotData(void) const override;                             // return nr of received bytes
    uint8_t mod_loadDataBlk(uint16_t len, uint8_t *buf) const override;
    uint8_t mod_setupSerial(struct TserialParams serialParameter) const override;
    uint8_t mod_getCurrentSerialSettings(struct TserialParams *serialParameter) const override;

    // Credit Card Terminal:
    uint8_t cc_power(bool on) const override;
    uint8_t cc_getHwState(struct Tcc_hw_state *cc_hw_state) const override;

*/

