#include <stdint.h>
#include <algorithm>

#include <QString>
#include <QDebug>
#include "storeINdata.h"
#include "tslib.h"
#include "shared_mem_buffer.h"


// gpi: grafical access to PI: access from external devices over device controller FOR GUI
// epi: external access from GUI to PI:  FOR external devices (DC)


// store power on/off condition of the devices to control the data request

static bool indat_savePrnPwr;

void indat_storePrinterPower(bool isOn) {
    indat_savePrnPwr=isOn;
}

bool indat_isPrinterOn() {
    return indat_savePrnPwr;
}

static bool indat_saveMifPwr;

void indat_storeMifarePower(bool isOn) {
    indat_saveMifPwr=isOn;
}

bool indat_isMifareOn() {
    return indat_saveMifPwr;
}

static bool indat_MdbIsOn;

void indat_storeMDBisOn(bool isOn) {
    indat_MdbIsOn=isOn;
}

bool indat_isMdbOn() {
    return indat_MdbIsOn;
}

void gpi_storeSlaveSerParams(uint8_t slaveBaudRate, uint8_t NrDataBits,
                             uint8_t parity, uint8_t NrStopBits) {
    // store numbers
    SharedMemBuffer::getData()->ndbs = NrDataBits;
    SharedMemBuffer::getData()->pari = parity;
    SharedMemBuffer::getData()->nsb = NrStopBits;
    SharedMemBuffer::getData()->br = slaveBaudRate;
}

void epi_getSlaveSerParams(uint8_t *slaveBaudRate, uint8_t *NrDataBits,
                           uint8_t *parity, uint8_t *NrStopBits) {

    *NrDataBits = SharedMemBuffer::getDataConst()->ndbs;
    *parity = SharedMemBuffer::getDataConst()->pari;
    *NrStopBits = SharedMemBuffer::getDataConst()->nsb;
    *slaveBaudRate = SharedMemBuffer::getDataConst()->br;
}

QString epi_getSlaveParamSTR() {
    QString mySt;

    switch (SharedMemBuffer::getDataConst()->br) {
        case 1:  mySt="1200   ";break;
        case 2:  mySt="9600   ";break;
        case 3:  mySt="19200  ";break;
        case 4:  mySt="38400  ";break;
        case 5:  mySt="57600  ";break;
        case 6:  mySt="115200 ";break;
    }

    char ctmp = SharedMemBuffer::getDataConst()->ndbs;
    ctmp += 0x30;
    mySt.append(ctmp);
    ctmp = SharedMemBuffer::getDataConst()->pari;
    mySt.append(ctmp);
    ctmp = SharedMemBuffer::getDataConst()->nsb;
    ctmp += 0x30;
    mySt.append(ctmp);
    return mySt;
}

// static QString genStrings[MAXNROF_GENSTR];
    // 0=HW   1=SW  2=State

void gpi_storeGenerals(uint8_t genNr, QString text) {
    // 0=HW   1=SW  2=State
    if (genNr < MAXNROF_GENSTR) {
        strncpy(&SharedMemBuffer::getData()->genStrings[genNr][0],
                text.toStdString().c_str(),
                sizeof(SharedMemBuffer::getDataConst()->genStrings[0]));
    }
}

QString epi_loadGenerals(uint8_t genNr) {
    if (genNr < MAXNROF_GENSTR) {
        if (genNr==2) { // DC2 State is shorter (8byte, not 64)
            //genStrings[2][8]=0;
            SharedMemBuffer::getData()->genStrings[2][8] = '\0';
        }
        return QString(SharedMemBuffer::getDataConst()->genStrings[genNr]);
    }
    return " ";
}

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

void gpi_storeUID(uint8_t const *buf8byteUid) {
    uint64_t udltmp=0;

    for (int ii=0; ii<8; ii++) {
        SharedMemBuffer::getData()->Sdata.UIDstr[ii] = buf8byteUid[ii];
        udltmp |= buf8byteUid[ii];
        udltmp <<= 8;
    }
    SharedMemBuffer::getData()->Sdata.slaveUID = udltmp;
}

void epi_getUIDdec(uint8_t *buf8byteUid) {
    for (int ii=0; ii<8; ii++) {
        buf8byteUid[ii] = SharedMemBuffer::getDataConst()->Sdata.UIDstr[ii];
    }
}

QString epi_getUIDstr() {
    // die UID besteht aus 8 bytes (8 dezimalzahlen)
    // -> umformen in hexstring

    QString myStr;
    for (int ii=0;ii<8; ii++) {
        myStr += QString::number(SharedMemBuffer::getDataConst()->Sdata.UIDstr[ii], 16);
        myStr += " ";
    }
    return myStr;
}

void gpi_backupSquareMode(uint8_t squMode) {
    SharedMemBuffer::getData()->getGlobalTime.squareOutMode = squMode;
}

uint8_t epi_getSquareMode() {
    return SharedMemBuffer::getDataConst()->getGlobalTime.squareOutMode;
}

void gpi_backupTime(uint8_t *timeBuffer, uint8_t Leng) {
    /*
    // Daten kommen in gleicher Reihenfolge vom Slave
    uint8_t *pTime;
    pTime=&getGlobalTime.hour;
    if (Leng>44) Leng=44;       // mehr brauch ma ned
    for (int nn=0; nn<Leng; nn++)
    {
        *pTime++=timeBuffer[nn];
    }*/

    // new, FastProt: 0=dayOfWeek 1=min 2=sec 3=hours 4=year 5=month 6=dayOfMonth
    SharedMemBuffer::getData()->getGlobalTime.second = Leng; // nur damit CompilerWarnung weg ist

    SharedMemBuffer::getData()->getGlobalTime.DayOfWeek = timeBuffer[0];
    SharedMemBuffer::getData()->getGlobalTime.minute = timeBuffer[1];
    SharedMemBuffer::getData()->getGlobalTime.second = timeBuffer[2];
    SharedMemBuffer::getData()->getGlobalTime.hour = timeBuffer[3];
    SharedMemBuffer::getData()->getGlobalTime.Year = timeBuffer[4];
    SharedMemBuffer::getData()->getGlobalTime.Month = timeBuffer[5];
    SharedMemBuffer::getData()->getGlobalTime.DayOfMonth = timeBuffer[6];
}

void epi_getTime(uint8_t *hh, uint8_t *mm, uint8_t *ss) {
    *hh = SharedMemBuffer::getDataConst()->getGlobalTime.hour;
    *mm = SharedMemBuffer::getDataConst()->getGlobalTime.minute;
    *ss = SharedMemBuffer::getDataConst()->getGlobalTime.second;
}

void epi_getDate(uint8_t *yy, uint8_t *mm, uint8_t *dd) {
    *yy = SharedMemBuffer::getDataConst()->getGlobalTime.Year;
    *mm = SharedMemBuffer::getDataConst()->getGlobalTime.Month;
    *dd = SharedMemBuffer::getDataConst()->getGlobalTime.DayOfMonth;
}

void epi_getToday(uint8_t *dow, uint16_t *minOfToday, uint32_t *secOfToday) {
    *dow = SharedMemBuffer::getDataConst()->getGlobalTime.DayOfWeek;
    *minOfToday = SharedMemBuffer::getDataConst()->getGlobalTime.MinutesOfToday;
    *secOfToday = SharedMemBuffer::getDataConst()->getGlobalTime.SecondsOfToday;
}

bool epi_isLeapYear(uint8_t *lastLeapYear, uint8_t *NextLeapYear) {
    *lastLeapYear = SharedMemBuffer::getDataConst()->getGlobalTime.lastLeap;
    *NextLeapYear = SharedMemBuffer::getDataConst()->getGlobalTime.nextLeap;
    return SharedMemBuffer::getDataConst()->getGlobalTime.IsLeapyear;
}

bool epi_isLeapYear() {
    return SharedMemBuffer::getDataConst()->getGlobalTime.IsLeapyear;
}

void epi_getSpecialWeekTimeDate(uint8_t *DayOfWeek,
                                uint8_t *HoursOfWeek,
                                uint16_t *MinutesOfWeek) {
    *DayOfWeek = SharedMemBuffer::getDataConst()->getGlobalTime.DayOfWeek;
    *HoursOfWeek = SharedMemBuffer::getDataConst()->getGlobalTime.hoursOfWeek;
    *MinutesOfWeek = SharedMemBuffer::getDataConst()->getGlobalTime.minOfWeek;
}

void epi_getSpecialMonthTimeDate(uint8_t *DayOfMonth,
                                 uint16_t *HoursOfMonth,
                                 uint16_t *MinutesOfMonth) {
    *DayOfMonth = SharedMemBuffer::getDataConst()->getGlobalTime.DayOfMonth;
    *HoursOfMonth = SharedMemBuffer::getDataConst()->getGlobalTime.hoursOfMonth;
    *MinutesOfMonth = SharedMemBuffer::getDataConst()->getGlobalTime.minOfMonth;
}

void epi_getSpecialYearTimeDate(uint16_t *DayOfYear,
                                uint16_t *HoursOfYear,
                                uint32_t *MinutesOfYear) {
    *DayOfYear = SharedMemBuffer::getDataConst()->getGlobalTime.dayOfYear;
    *HoursOfYear = SharedMemBuffer::getDataConst()->getGlobalTime.hoursOfYear;
    *MinutesOfYear = SharedMemBuffer::getDataConst()->getGlobalTime.minOfYear;
}

QString epi_getRtcTimeStr(uint8_t timeStyle) {
    // style: 0: hh:mm    1: hh:mm:ss
    QString mystr=nullptr, tempStr=nullptr;

    tempStr.setNum(SharedMemBuffer::getDataConst()->getGlobalTime.hour, 10);
    mystr=tempStr.rightJustified(2,'0',false);  // macht feste Länge, 5->05
    mystr.append(':');
    tempStr.setNum(SharedMemBuffer::getDataConst()->getGlobalTime.minute, 10);
    //mystr.append(tempStr);
    mystr+=tempStr.rightJustified(2,'0',false);
    //mystr.append(':');    // so
    //mystr+=':';             // oder so, =gleich

    if (timeStyle==1)     //  hh:mm:ss
    {
        mystr.append(':');
        tempStr.setNum(SharedMemBuffer::getDataConst()->getGlobalTime.second, 10);
        mystr.append(tempStr.rightJustified(2,'0',false));  // wie +=
    }
    return mystr;
}

QString epi_getRtcDateStr(uint8_t dateStyle) {
    // 1=german dd.mm.yy   2=american yy/mm/dd   3=mm.dd.yy
    QString tmpStr=nullptr, YYstr=nullptr, MMstr=nullptr, DDstr=nullptr, mystr=nullptr;
    mystr.clear();

    tmpStr.setNum(SharedMemBuffer::getDataConst()->getGlobalTime.Year, 10);
    YYstr=tmpStr.rightJustified(4,'0',false);   // immer vierstellig
    YYstr[0]='2';                               // 2000 dazu

    tmpStr.setNum(SharedMemBuffer::getDataConst()->getGlobalTime.Month, 10);
    MMstr=tmpStr.rightJustified(2,'0',false);

    tmpStr.setNum(SharedMemBuffer::getDataConst()->getGlobalTime.DayOfMonth, 10);
    DDstr=tmpStr.rightJustified(2,'0',false);

    if (dateStyle==1)     // Germany dd.mm.yy
    {
        mystr=DDstr + '.' + MMstr + '.' + YYstr;
    } else
    if (dateStyle==2)     // american yy/mm/dd
    {
        mystr=YYstr + '/' + MMstr + '/' + DDstr;
    } else
       // mm.dd.yy
    {
        mystr=MMstr + '.' + DDstr + '.' + YYstr;
    }
    return mystr;
}


QString epi_getSlaveTimeDateStr() {
    QString myStr;
    myStr=epi_getRtcTimeStr(1) + "     " + epi_getRtcDateStr(1);
    return myStr;

}

// ///////////////////////////////////////////////////////////////////////////////////
//          analog values
// ///////////////////////////////////////////////////////////////////////////////////


uint8_t gpi_getMaxNrAIs() {
    return MAXNROF_AI;
}

void gpi_storeAIs(uint8_t aiNr, uint16_t val) {
    if (aiNr < MAXNROF_AI) {
        SharedMemBuffer::getData()->AI_val[aiNr] = val;
    }
}

uint16_t epi_loadAIs(uint8_t aiNr) {
    if (aiNr < MAXNROF_AI) {
        return SharedMemBuffer::getDataConst()->AI_val[aiNr];
    }
    return 0;
}


//--------------
// measurement values
// ADC0: temp
// 1: voltage
// 2: brightness

uint32_t epi_loadMeasureValue(uint8_t ValueNr) {
    // ValueNr 0=ADC0, 1=ADC1 aso...
    if (ValueNr < MAXNROF_MEASURE) {
        return SharedMemBuffer::getDataConst()->Sdata.measurement[ValueNr];
    }
    return 0;
}

void gpi_storeMeasureValue(uint8_t ValueNr, uint32_t val) {
    // in mV, also bis 65,535V
    if (ValueNr < MAXNROF_MEASURE) {
        SharedMemBuffer::getData()->Sdata.measurement[ValueNr] = val;
    }
}

QString epi_getSlaveTemperatureStr() {
    char myStr[8], halfDegree=0, Minus=0, oneChar;
    int16_t val=0, pp, einer, zehner;
    QString myqStr;

    //qDebug() << "AIN0: " << epi_loadAIs(0) << "AIN1: " << epi_loadAIs(1);

    uint32_t meas_temper=epi_loadMeasureValue(MEASCHAN_TEMPERATURE);
    // im SaxFormat gespeichert, hier umwandeln in String

    //qDebug() << "meas_temper: " << meas_temper;


    for (pp=0; pp<8; pp++) myStr[pp]=0;
    if (meas_temper&1)      // ungerade, also ,5°C
    {
        halfDegree=1;
        meas_temper &=0xFFFE;    // um 0,5°C abrunden
    }
    if (meas_temper<100)
    {
        Minus=1;
        val=int16_t(meas_temper)/2;
        val-=50;
    } else
    {
        val=int16_t(meas_temper)-100;
        val/=2;
    }
    pp=0;   // pointer auf string
    if (Minus)
        myStr[pp++]='-';
    // val is now 0..150 for pos Temp or 0..49 for negativ temperature
    if (val<10)
    {
        // only one digit, just change to ascii
        oneChar = char(val)+0x30;
        if (tslib_isDecAsciiNumber(oneChar))
            myStr[pp++]=oneChar;
        else
            myStr[pp++]='0';
    } else
    if (val<100)
    {
        // 10...99
        einer=val%10;
        zehner=val/10;
        //myStr[pp++]=char(zehner);
        //myStr[pp++]=char(einer);

        oneChar = char(zehner)+0x30;
        if (tslib_isDecAsciiNumber(oneChar))
            myStr[pp++]=oneChar;
        else
            myStr[pp++]='0';

        oneChar = char(einer)+0x30;
        if (tslib_isDecAsciiNumber(oneChar))
            myStr[pp++]=oneChar;
        else
            myStr[pp++]='0';

    } else
    {
        // 100...150
        myStr[pp++]='1';    // hunderter Stelle immer 1
        val-=100;
        einer=val%10;
        zehner=val/10;
        //myStr[pp++]=char(zehner)+0x30;
        //myStr[pp++]=char(einer)+0x30;
        oneChar = char(zehner)+0x30;
        if (tslib_isDecAsciiNumber(oneChar))
            myStr[pp++]=oneChar;
        else
            myStr[pp++]='0';

        oneChar = char(einer)+0x30;
        if (tslib_isDecAsciiNumber(oneChar))
            myStr[pp++]=oneChar;
        else
            myStr[pp++]='0';
    }
    myStr[pp++]=',';
    if (halfDegree)
        myStr[pp++]='5';
    else
        myStr[pp++]='0';
    myqStr.clear();
    myqStr.append(myStr);
    myqStr.append("°C");
    return myqStr;
}

QString epi_getSlaveVoltageStr()
{
    // value in "meas_volt" in mV, also bis 65,535V. Value range [6000...16000] (6V...16V)
    QString myqStr;
    uint32_t vor, nach, tmp32;
    uint16_t pp;
    char myStr[12], ke; //, kz, kh;

    uint32_t ultmp=epi_loadMeasureValue(MEASCHAN_VOLTAGE);
    for (pp=0; pp<12; pp++) myStr[pp]=0;

    //qDebug() << ultmp << "mV";

    myqStr.clear();
    vor=ultmp/1000;
    //qDebug() << "vor: " << vor;

    nach=ultmp%1000;
    //qDebug() << "nach: " << nach;
    pp=0;
    if (vor>9)
    {
        myStr[pp++]=char(vor/10)+0x30;
    }
    myStr[pp++]=char(vor%10)+0x30;
    myStr[pp++]=',';

    ke=char(nach/100);
    //qDebug() << "ke: " << ke;
    myStr[pp++]=char(ke)+0x30;

    tmp32=nach%100;
    ke=char(tmp32/10);
    //qDebug() << "ke: " << ke;
    myStr[pp++]=char(ke)+0x30;

    tmp32=nach%10;
    ke=char(tmp32);
    //qDebug() << "ke: " << ke;
    myStr[pp++]=char(ke)+0x30;


    myStr[pp++]='V';
    myqStr.append(myStr);
    return myqStr;
}



// ///////////////////////////////////////////////////////////////////////////////////
//          digital inputs
// ///////////////////////////////////////////////////////////////////////////////////

/* come all in with 0x1201:
D0: upper door  D1: low door  D2:vault door
D3: cash box    D4: bill box in
D5: bit 0: upper lockbar up   bit1:down
D6: bit 0: lower lockbar up   bit1:down

D7: 0
D7: DI_contact Power Is On

D8: OptoIn 1,2
D9: Aux0...5
D10:Wake from ptu
D11: DI Wake From Mdb
D12: Ready from printer
D13: Coin Shutter Input
D14: CoinEscrow switch
D15: Mifare IN
D16: Modem_Wake In

D18: DI Mif Pwr is on
D19: DI MDB_TxD_rdBack
D20: DI Aux Pwr is on
D21: DI GSM Pwr from PO2 is ON
D22:  DI Credit Pwr from PO2 is on
        =DI RdBack Credit Wake
D23:  DI Printer Pwr from PO2 is on
D24:  DI MDB Pwr from PO2 is on
  */

void gpi_storeDI_doorSwitches(uint8_t upperDoor,
                              uint8_t lowerDoor,
                              uint8_t vaultDoor) {
    SharedMemBuffer::getData()->din.doorSwitch = 0;
    if (upperDoor) SharedMemBuffer::getData()->din.doorSwitch |= 1;
    if (lowerDoor) SharedMemBuffer::getData()->din.doorSwitch |= 2;
    if (vaultDoor) SharedMemBuffer::getData()->din.doorSwitch |= 4;
}

uint8_t epi_getDI_doorSwitches(void) {
    // bit0: upper door  1: low door  2:vault door
    return SharedMemBuffer::getDataConst()->din.doorSwitch;
}

void gpi_storeDI_vaultSwitches(uint8_t CashBoxIn, uint8_t BillBoxIn) {
    SharedMemBuffer::getData()->din.vaultSwitch = 0;
    if (CashBoxIn) SharedMemBuffer::getData()->din.vaultSwitch |= 1;
    if (BillBoxIn) SharedMemBuffer::getData()->din.vaultSwitch |= 2;
}

uint8_t epi_getDI_vaultSwitches(void) {
    // bit0: cash box    1: bill box in
    return SharedMemBuffer::getData()->din.vaultSwitch;
}

void gpi_storeDI_lockSwitches(uint8_t indatUL, uint8_t indatLL) {
    // D5: bit 0: upper lockbar up   bit1:down
    // D6: bit 0: lower lockbar up   bit1:down
    SharedMemBuffer::getData()->din.lockSwitch = 0;
    if (indatUL & 1) SharedMemBuffer::getData()->din.lockSwitch |= 1;
    if (indatUL & 2) SharedMemBuffer::getData()->din.lockSwitch |= 2;
    if (indatLL & 1) SharedMemBuffer::getData()->din.lockSwitch |= 4;
    if (indatLL & 2) SharedMemBuffer::getData()->din.lockSwitch |= 8;
}

uint8_t epi_getDI_lockSwitches(void) {
    // retval: bit 0: upper lockbar up   bit1: upper lockbar is down
    //         bit 2: lower lockbar up   bit1: lower lockbar is down
    return SharedMemBuffer::getData()->din.lockSwitch;
}

void gpi_storeDI_optos(uint8_t indatOpto) {
    // OptoIn bit 0,1: optoin 1,2
    SharedMemBuffer::getData()->din.opto = 0;
    if (indatOpto & 1) SharedMemBuffer::getData()->din.opto |= 1;
    if (indatOpto & 2) SharedMemBuffer::getData()->din.opto |= 2;
}

uint8_t epi_getDI_optos(void) {
    // bit0: opto in 1    1: opto in 2
    return SharedMemBuffer::getDataConst()->din.opto;
}

uint8_t gpi_storeDI_auxIn(uint8_t aux) { // Aux0...5
    return SharedMemBuffer::getData()->din.aux = aux;
}

uint8_t epi_getDI_auxIn(void) { // bit0: auxin 1  ...  5: auxin 6
    return SharedMemBuffer::getDataConst()->din.aux;
}

bool gpi_storeDI_ptuWake(bool w) {
    return SharedMemBuffer::getData()->din.wakeFromPtu = w;
}

bool epi_getDI_ptuWake(void) {
    return SharedMemBuffer::getDataConst()->din.wakeFromPtu;
}

bool gpi_storeDI_mbdWake(bool w) {
    return SharedMemBuffer::getData()->din.wakeFromMdb = w;
}

bool epi_getDI_mdbWake(void) {
    return SharedMemBuffer::getDataConst()->din.wakeFromMdb;
}

bool gpi_storeDI_prnReady(bool ready) {
    return SharedMemBuffer::getData()->din.PrnReady = ready;
}

bool epi_getDI_prnReady(void) {
    return SharedMemBuffer::getDataConst()->din.PrnReady;
}

bool gpi_storeDI_CoinAttach(bool attach) {
    return SharedMemBuffer::getData()->din.CoinAttach = attach;
}

bool epi_getDI_CoinAttach(void) {
    return SharedMemBuffer::getDataConst()->din.CoinAttach;
}

bool gpi_storeDI_CoinEscrow(bool ce) {
    return SharedMemBuffer::getData()->din.CoinEscrowOpen = ce;
}

bool epi_getDI_CoinEscrow(void) {
    return SharedMemBuffer::getDataConst()->din.CoinEscrowOpen;
}

bool gpi_storeDI_mifareCardTapped(bool tapped) {
    return SharedMemBuffer::getData()->din.mifCardTap = tapped;
}

bool epi_getDI_mifareCardTapped(void) {
    return SharedMemBuffer::getDataConst()->din.mifCardTap;
}

bool gpi_storeDI_modemWake(bool w) {
    return SharedMemBuffer::getData()->din.wakeFromModem = w;
}

bool epi_getDI_modemWake(void) {
    return SharedMemBuffer::getDataConst()->din.mifCardTap;
}

bool gpi_storeDI_contactPowerIsOn(bool on) {
    return SharedMemBuffer::getData()->din.contactPwrOn = on;
}

bool epi_getDI_contactPwr(void) { // invertiert!
    return !SharedMemBuffer::getDataConst()->din.contactPwrOn;
}

bool gpi_storeDI_MifarePowerIsOn(bool on) {
    return SharedMemBuffer::getData()->din.mifarePwrOn = on;
}

bool epi_getDI_mifarePwr(void) {
    return SharedMemBuffer::getDataConst()->din.mifarePwrOn;
}

bool gpi_storeDI_readbackMdbTxD(bool rdbkMdbTxd) {
    return SharedMemBuffer::getData()->din.rdbk_mdbTxd = rdbkMdbTxd;
}

bool epi_getDI_mdbTxd(void) {
    return SharedMemBuffer::getDataConst()->din.rdbk_mdbTxd;
}

bool gpi_storeDI_AuxPowerIsOn(bool on) {
    return SharedMemBuffer::getData()->din.AuxPwrOn = on;
}

bool epi_getDI_auxPwr(void) {
    return SharedMemBuffer::getDataConst()->din.AuxPwrOn;
}

bool gpi_storeDI_GsmPowerIsOn(bool on) {
    return SharedMemBuffer::getData()->din.gsmPwrOn = on;
}

bool epi_getDI_gsmPwr(void) {
    return SharedMemBuffer::getDataConst()->din.gsmPwrOn;
}

bool gpi_storeDI_CreditPowerIsOn(bool on) {
    // invertieren!!!
    return SharedMemBuffer::getData()->din.creditPwrOn = !on;
}

bool epi_getDI_creditPwr(void) {
    return SharedMemBuffer::getDataConst()->din.creditPwrOn;
}

bool gpi_storeDI_PrinterPowerIsOn(bool on) {
    return SharedMemBuffer::getData()->din.printerPwrOn = on;
}

bool epi_getDI_printerPwr(void) {
    return SharedMemBuffer::getDataConst()->din.printerPwrOn;
}

bool gpi_storeDI_MdbPowerIsOn(bool on) {
    return SharedMemBuffer::getData()->din.mdbPwrOn = on;
}

bool epi_getDI_mdbPwr(void) {
    return SharedMemBuffer::getDataConst()->din.mdbPwrOn;
}

bool gpi_storeDI_rejMot_home(bool reject) {
    return SharedMemBuffer::getData()->din.rejMot_home = reject;
}

bool epi_getDI_rejectMotor_homepos(void) {
    return SharedMemBuffer::getDataConst()->din.rejMot_home;
}

uint8_t gpi_storeDI_paperLow(uint8_t sensor) {
    // 0: Sensor sees paper 1: no paper 99: off
    return SharedMemBuffer::getData()->din.npe_sensor = sensor;
}

uint8_t epi_getDI_npe_sensor(void) {
    return SharedMemBuffer::getDataConst()->din.npe_sensor;
}



// ///////////////////////////////////////////////////////////////////////////////////
//          readaback digital outputs
// ///////////////////////////////////////////////////////////////////////////////////


/*
D0  bit0: MDB devices 0=off 1=on
    bit1: MDB bus power
    bit2: MDB WakeOut

D1=Printer
D2=Credit
D3=Modem

D5: serial drv on/off, Serial mux1, Serial mux2
D6: Leds, Fan,
D7: Siren and relay
D8: PtuWakeOut
D9: Power Aux/Barcode
D10: AuxDir 1...6
D11: AuxOut 1...6
D12: Coin shutter output
D13: CoinEscrow Outputs
*/

uint8_t gpi_storeDO_mdbRxTst(uint8_t mdbRxTst) {
    return SharedMemBuffer::getData()->dout.mbdRxTst = mdbRxTst;
}

bool epi_getDO_mdbRxTestOut(void) {
    return SharedMemBuffer::getData()->dout.mbdRxTst & 1;
}

uint8_t gpi_storeDO_motorOutputs(uint8_t motorBits) {
    //D1: motor outputs bit0: upper lock forw bit 1 backw
    //                          Bit2: lowLock forw  bit3: LL backw
    return SharedMemBuffer::getData()->dout.motorBits = motorBits;
}

uint8_t epi_getDO_motorOuts(void) {
    // bit0: upper lock forward    bit 1 backward
    // bit2: lower lock forward    bit 3 backward
    return SharedMemBuffer::getDataConst()->dout.motorBits;
}

uint8_t gpi_storeDO_serialSwitch(uint8_t serialSwitch) {  // serial drv on/off, Serial mux1, Serial mux2
    return SharedMemBuffer::getData()->dout.serialSwitch = serialSwitch;
}

uint8_t epi_getDO_serialSwitch(void) {
    // serial drv on/off, Serial mux1, Serial mux2
    return SharedMemBuffer::getDataConst()->dout.serialSwitch;
}

bool epi_getDO_serialDriverIsOn(void) {
    return SharedMemBuffer::getDataConst()->dout.serialSwitch & 1;
}

bool epi_getDO_serialMux1isSetToPrinter(void) {
    // mux1 off: serial is switched to printer
    return (SharedMemBuffer::getDataConst()->dout.serialSwitch & 2) == 0;
}

bool epi_getDO_serialMux1isSetToModem(void) {
    // mux1 on: serial is switched to modem
    return (SharedMemBuffer::getDataConst()->dout.serialSwitch & 2) > 0;
}

bool epi_getDO_serialMux2isSetToCredit(void) {
    // mux2 off: serial is switched to credit card terminal
    return (SharedMemBuffer::getDataConst()->dout.serialSwitch & 4) == 0;
}

bool epi_getDO_serialMux2isSetToMifare(void) {
    // mux2 on: serial is switched to mifare reader
    return (SharedMemBuffer::getDataConst()->dout.serialSwitch & 4) > 0;
}

uint8_t gpi_storeDO_ledsAndFan(uint8_t ledState) {
    // bit0: coinled  1:front_illu 2: paper-led  3:pinpad-led  4:start-led  5:service-led  6:fan
    return SharedMemBuffer::getData()->dout.ledsAndFan = ledState;
}

bool epi_getDO_led_coin(void) {
    return (SharedMemBuffer::getDataConst()->dout.ledsAndFan & 1);
}

bool epi_getDO_led_front(void) {
    return (SharedMemBuffer::getDataConst()->dout.ledsAndFan & 2);
}

bool epi_getDO_led_ticket(void) {
    return (SharedMemBuffer::getDataConst()->dout.ledsAndFan & 4);
}

bool epi_getDO_led_pin(void) {
    return (SharedMemBuffer::getDataConst()->dout.ledsAndFan & 8);
}

bool epi_getDO_led_start(void) {
    return (SharedMemBuffer::getDataConst()->dout.ledsAndFan & 16);
}

bool epi_getDO_led_inside(void) {
    return (SharedMemBuffer::getDataConst()->dout.ledsAndFan & 32);
}

bool epi_getDO_fan(void) {
    return (SharedMemBuffer::getDataConst()->dout.ledsAndFan & 64);
}

uint8_t gpi_storeDO_sirenAndRelay(uint8_t sirenRelay) {
    // bit0: siren  1:relay
    return SharedMemBuffer::getData()->dout.laermUndRelay = sirenRelay;
}

bool epi_getDO_sirene(void) {
    return SharedMemBuffer::getDataConst()->dout.laermUndRelay & 1;
}

bool epi_getDO_relay(void) {
    return SharedMemBuffer::getDataConst()->dout.laermUndRelay & 2;
}

uint8_t gpi_storeDO_ptuWake(uint8_t state) {
    return SharedMemBuffer::getData()->dout.ptuWake = state;
}

bool epi_getDO_ptuWake(void) {
    return SharedMemBuffer::getDataConst()->dout.ptuWake > 0;
}

uint8_t gpi_storeDO_auxPower(uint8_t pwr) {
    return SharedMemBuffer::getData()->dout.auxPower = pwr;
}

bool epi_getDO_auxPower(void) {
    return SharedMemBuffer::getDataConst()->dout.auxPower > 0;
}

uint8_t gpi_storeDO_coinShutter(uint8_t state) {
    return SharedMemBuffer::getData()->dout.coinShutter = state;
}

bool epi_getDO_coinShutterOpen(void) {
    // bit0: Coin shutter output,    bit1: input-test-output
    return SharedMemBuffer::getDataConst()->dout.coinShutter & 1;
}

bool epi_getDO_coinShutterTest(void) {
    // bit0: Coin shutter output,    bit1: input-test-output
    return SharedMemBuffer::getDataConst()->dout.coinShutter & 2;
}

uint8_t gpi_storeDO_coinEscrow(uint8_t state) {
    return SharedMemBuffer::getData()->dout.coinEscrow = state;
}

uint8_t epi_getDO_coinEscrow(void) {
    // retval: 1:return flap is open   2:take flap is open    0:closed
    if (SharedMemBuffer::getData()->dout.coinEscrow & 1) {
        return 1; // return flap is open
    }
    if (SharedMemBuffer::getData()->dout.coinEscrow & 2) {
        return 2;           // take flap is open
    }
    return 0;
}

uint8_t gpi_storeDO_printerPwrOn(uint8_t state) {
    return SharedMemBuffer::getData()->dout.printerPower = state;
}

uint8_t epi_getDO_printerPwr(void) {
    return SharedMemBuffer::getDataConst()->dout.printerPower;
}

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//----------------------------- Mifare Card Reader -----------------------------------
uint8_t gpi_storeMifReaderStateAndCardType(uint8_t const *buf) {
    // retval 0=OK 1=error host buffer too small
    memset(SharedMemBuffer::getData()->Sdata.MIF_STATE, 0x00,
           sizeof(SharedMemBuffer::getData()->Sdata.MIF_STATE));
    memcpy(SharedMemBuffer::getData()->Sdata.MIF_STATE, buf, 8);
    return 0;       // OK
}

/* 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)


old long version
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 "SL025-1.8"
byte16: 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
*/

uint8_t epi_restoreMifState(uint8_t *buf, uint8_t maxBufferSize) {
    // HWapi can read States from DC
    if (maxBufferSize<8) {
        return 1;   // error
    }
    memcpy(buf, SharedMemBuffer::getData()->Sdata.MIF_STATE, 8);
    return 0;       // OK
}

// data come in blockwise, so safe them blockwise as well
bool gpi_storeMifCardData(uint8_t blkNr, uint8_t const *receivedData) {
    if (blkNr<12) {
        memcpy(&SharedMemBuffer::getData()->Sdata.MIF_DATA[blkNr][0], receivedData, 64);
        return true;
    }
    return false;
}

uint8_t epi_restoreMifData(uint8_t blkNr, uint8_t *buf, uint8_t maxBufferSize) {
    if (blkNr>11 || maxBufferSize<64) {
        return 1;   // error
    }

    memcpy(buf, &SharedMemBuffer::getDataConst()->Sdata.MIF_DATA[blkNr][0], 64);
    return 0;   // ois OK
}

void gpi_storeNewMifareCard(uint8_t typ, uint8_t const *holder) {
    SharedMemBuffer::getData()->mif_cardType = typ;
    strncpy((char *)holder, (char *)SharedMemBuffer::getData()->mif_cardHolder, 7);
    SharedMemBuffer::getData()->mif_cardHolder[7] = '\0';
}

uint8_t epi_mifGetCardType(uint8_t const *holder) {
    //holder[8] = name of card holder
    // retval Type of MifareCard, 1=upper door, 2=lower door 3=test printer 4=test coins
    strncpy((char *)SharedMemBuffer::getData()->mif_cardHolder, (char *)holder, 7);
    return SharedMemBuffer::getData()->mif_cardType;
}

void epi_restorePrinterState(uint8_t *buf) {
    memcpy((char *)buf, (char *)SharedMemBuffer::getData()->Sdata.PRN_STATE,
           sizeof(SharedMemBuffer::getData()->Sdata.PRN_STATE));
}

void gpi_storePrinterState(uint8_t const *buf) {
    memcpy((char *)SharedMemBuffer::getData()->Sdata.PRN_STATE, (char *)buf,
           sizeof(SharedMemBuffer::getData()->Sdata.PRN_STATE));
}

void epi_restorePrinterFonts(uint8_t *buf) {
    memcpy((char *)buf, (char *)SharedMemBuffer::getData()->Sdata.PRN_FONTS,
           sizeof(SharedMemBuffer::getData()->Sdata.PRN_FONTS));
}

void gpi_storePrinterFonts(uint8_t const *buf) {
    memcpy((char *)SharedMemBuffer::getData()->Sdata.PRN_FONTS, (char *)buf,
           sizeof(SharedMemBuffer::getData()->Sdata.PRN_FONTS));
}

// DB0: mdb_bus_ready (switched on)
// DB1: rdBackV12devicePower
// DB2: rdBackV5busPwr
bool gpi_storeMdbState(bool busReady, bool V12on, bool V5on) {
    SharedMemBuffer::getData()->Sdata.mdb_busRdy = busReady;
    SharedMemBuffer::getData()->Sdata.mdb_V12on = V12on;
    SharedMemBuffer::getData()->Sdata.mdb_V5on = V5on;
    return true;
}

bool epi_restoreMdbBusReady(void) {
    return SharedMemBuffer::getDataConst()->Sdata.mdb_busRdy;
}

bool epi_restoreMdbV12Ready(void) {
    return SharedMemBuffer::getDataConst()->Sdata.mdb_V12on;
}

bool epi_restoreMdbV5Ready(void) {
    return SharedMemBuffer::getDataConst()->Sdata.mdb_V5on;
}

// 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: nr of received (payload) data bytes (apart from ACK, can be 0....34)
// DB3...DB38: rec.data (payload)
void gpi_storeMdbResponse(uint8_t leng, uint8_t const *data) {
    memset(&SharedMemBuffer::getData()->Sdata.RecBuff[0], 0x00,
           sizeof(SharedMemBuffer::getData()->Sdata.RecBuff));
    SharedMemBuffer::getData()->Sdata.mdbNrOfRecData = leng;
    memcpy((char *)&SharedMemBuffer::getData()->Sdata.RecBuff[0],
           (char const *)data, leng);
}

void epi_restoreMdbResponse(uint8_t *leng, uint8_t *data) {
    *leng = SharedMemBuffer::getDataConst()->Sdata.mdbNrOfRecData;
    memcpy((char *)data,
           (char *)&SharedMemBuffer::getDataConst()->Sdata.RecBuff[0], *leng);
}

void gpi_storeEmpSettings(uint8_t leng, uint8_t const *data) {
    leng = std::min(leng, (uint8_t)(64));
    memset(&SharedMemBuffer::getData()->Sdata.emp_settingsBuff[0], 0x00,
           sizeof(SharedMemBuffer::getData()->Sdata.emp_settingsBuff));
    SharedMemBuffer::getData()->Sdata.empNrOfsettings = leng;
    memcpy((char *)&SharedMemBuffer::getData()->Sdata.emp_settingsBuff[0],
           (char const *)data, leng);
}

void epi_restoreEmpSettings(uint8_t *leng, uint8_t *data) {
    *leng = SharedMemBuffer::getDataConst()->Sdata.empNrOfsettings;
    memcpy((char *)data,
           (char *)&SharedMemBuffer::getData()->Sdata.emp_settingsBuff[0],
            *leng);
}

// ......................................................................
// Münzbuffer[10]: Münze für Münze auslesen (LIFO)
// 4.5.21

static void sub_enterData(uint8_t valid, uint8_t signal,
                          uint8_t error, uint16_t value) {
    if (SharedMemBuffer::getDataConst()->ctr_gotCoin < MEMDEPTH_GOTCOINS) {
        uint8_t const gc = SharedMemBuffer::getDataConst()->ctr_gotCoin;
        SharedMemBuffer::getData()->gotCoin[gc].valid = valid;
        SharedMemBuffer::getData()->gotCoin[gc].signal = signal;
        SharedMemBuffer::getData()->gotCoin[gc].error = error;
        SharedMemBuffer::getData()->gotCoin[gc].value = value;
    }
    SharedMemBuffer::getData()->ctr_gotCoin += 1;
}

void gpi_storeEmpCoinSignal(uint8_t leng, uint8_t const *data) {
    // leng is number of coin record with 5 bytes each
    uint8_t LL = leng;    //  nr of coin records
    uint16_t vv, pp = 0;

    //while (LL>0)  // with FastProtocol only one coin
    {
        vv=uchar2uint(data[pp+4], data[pp+3]);
        sub_enterData(data[pp], data[pp+1], data[pp+2], vv );
        pp+=5;
        LL--;
    }
}

uint8_t epi_isNewCoinLeft(void) {
    // retval: 0...16 coins left in FIFO
    return SharedMemBuffer::getDataConst()->ctr_gotCoin;
}

void epi_restoreEmpCoinSignal(uint8_t *valid, uint8_t *signal,
                              uint8_t *error, uint16_t *value) {
    SharedMemBuffer::getData()->ctr_gotCoin -= 1;
    if (SharedMemBuffer::getDataConst()->ctr_gotCoin < MEMDEPTH_GOTCOINS) {
        uint8_t const gc = SharedMemBuffer::getDataConst()->ctr_gotCoin;
        *valid = SharedMemBuffer::getDataConst()->gotCoin[gc].valid;
        *signal = SharedMemBuffer::getDataConst()->gotCoin[gc].signal;
        *error = SharedMemBuffer::getDataConst()->gotCoin[gc].error;
        *value = SharedMemBuffer::getDataConst()->gotCoin[gc].value;
    }
}

void gpi_storeRbDeviceSettings(uint8_t leng, uint8_t const *data) { // getestet am 12.4.23TS
    leng = std::min(leng, (uint8_t)(64));
    SharedMemBuffer::getData()->Sdata.NrOfDeviceSetting = leng;
    memset((char *)&SharedMemBuffer::getData()->Sdata.DeviceSettingBuff[0],
            0x00, sizeof(SharedMemBuffer::getData()->Sdata.DeviceSettingBuff));
    memcpy((char *)&SharedMemBuffer::getData()->Sdata.DeviceSettingBuff[0],
           (char const *)data, leng);
}

void epi_restoreRbDeviceSettings(uint8_t *leng, uint8_t *data) { // getestet am 12.4.23TS
    *leng = SharedMemBuffer::getDataConst()->Sdata.NrOfDeviceSetting;
    memcpy((char *)data,
           (char const *)&SharedMemBuffer::getDataConst()->Sdata.DeviceSettingBuff[0],
           *leng);
}

void gpi_storeMachineIDsettings(uint8_t leng, uint8_t const *data) {
    leng = std::min(leng, (uint8_t)(64));
    SharedMemBuffer::getData()->Sdata.NrOfMachineIDSetting = leng;
    memset((char *)&SharedMemBuffer::getData()->Sdata.NrOfMachineIDBuff[0],
            0x00, sizeof(SharedMemBuffer::getData()->Sdata.NrOfMachineIDBuff));
    memcpy((char *)&SharedMemBuffer::getData()->Sdata.NrOfMachineIDBuff[0],
           (char const *)data, leng);
}

void epi_restoreMachineIDsettings(uint8_t *leng, uint8_t *data) {
    *leng = SharedMemBuffer::getDataConst()->Sdata.NrOfMachineIDSetting;
    memcpy((char *)data,
           (char const *)&SharedMemBuffer::getDataConst()->Sdata.NrOfMachineIDBuff[0],
           *leng);
}


static uint8_t  p_lastCoin;

void epi_clearCurrentPayment(void) {
    // call at beginning of coin collection
    SharedMemBuffer::getData()->store.insertedAmount = 0;
    p_lastCoin = 0;
}

void gpi_storeCurrentPayment(uint32_t insertedAmount,
                             uint16_t lastCoinType, uint16_t lastCoinValue) {
    SharedMemBuffer::getData()->store.insertedAmount = insertedAmount;
    SharedMemBuffer::getData()->store.lastCoinType[p_lastCoin] = lastCoinType;
    SharedMemBuffer::getData()->store.lastCoinValue[p_lastCoin] = lastCoinValue;
    p_lastCoin++;
}

uint32_t epi_CurrentPaymentGetAmount(void) {
    return SharedMemBuffer::getDataConst()->store.insertedAmount;
}

uint16_t epi_CurrentPaymentGetLastCoin(void) {
    uint8_t pp = p_lastCoin;
    if (pp==0) {
        return 0;       // noch keine Münze erhalten
    }
    if (pp>0) {
        pp--;
    }
    return SharedMemBuffer::getDataConst()->store.lastCoinValue[pp];
}

bool epi_CurrentPaymentGetAllCoins(uint16_t *types, uint16_t *values) {
    // alle bei diesem Verkauf eingeworfenen Münzen sind gespeichert falls die jmd. braucht
    if (p_lastCoin==0) {
        return false;
    }
    for (int nn=0; nn<64; nn++) {
        types[nn] = SharedMemBuffer::getDataConst()->store.lastCoinType[nn];
        values[nn] = SharedMemBuffer::getDataConst()->store.lastCoinValue[nn];
    }
    return true;
}

void gpi_storeWakeSources(uint8_t const *receivedData) {
    SharedMemBuffer::getData()->store.wakeSrc = 0;
    for (int nn=5; nn>=0; nn--) {
        uint8_t const uctmp = receivedData[nn];
        SharedMemBuffer::getData()->store.wakeSrc |= uctmp;
        SharedMemBuffer::getData()->store.wakeSrc <<= 8;
    }
    SharedMemBuffer::getData()->store.wakeReason = receivedData[6];

}

uint64_t epi_getWakeSources(void) {
    return SharedMemBuffer::getDataConst()->store.wakeSrc;
}

uint8_t epi_getWakeReason(void)
{
    return SharedMemBuffer::getDataConst()->store.wakeReason;
}



void gpi_storeExtendedTime(uint8_t leng, uint8_t const *data) {
    leng = std::min(leng, (uint8_t)(64));
    SharedMemBuffer::getData()->store.rbDevParamLen = leng;
    memset((char *)(&SharedMemBuffer::getData()->store.rbDevParams[0]), 0x00,
           sizeof(SharedMemBuffer::getData()->store.rbDevParams));
    memcpy((char *)(&SharedMemBuffer::getData()->store.rbDevParams[0]),
           (char const *)data, leng);
}

void epi_restoreExtendedTime(uint8_t *leng, uint8_t *data) {
    *leng = SharedMemBuffer::getDataConst()->store.rbDevParamLen;
    memcpy((char *)data,
           (char const *)(&SharedMemBuffer::getData()->store.rbDevParams[0]),
            *leng);
}

// store device conditions
void gpi_storeDeviceConditions(uint8_t leng, uint8_t const *data) {
    leng = std::min(leng, (uint8_t)(64));
    SharedMemBuffer::getData()->store.deviceCondLen = leng;
    memset((char *)(&SharedMemBuffer::getData()->store.deviceCond[0]), 0x00,
           sizeof(SharedMemBuffer::getData()->store.deviceCond));
    memcpy((char *)(&SharedMemBuffer::getData()->store.deviceCond[0]),
           (char const *)data, leng);
}

void epi_restoreDeviceConditions(uint8_t *leng, uint8_t *data) {
    *leng = SharedMemBuffer::getDataConst()->store.deviceCondLen;
    memcpy((char *)data,
           (char const *)(&SharedMemBuffer::getData()->store.deviceCond[0]),
            *leng);
}

// store dynamic machine conditions
void gpi_storeDynMachineConditions(uint8_t leng, uint8_t const *data) {
    SharedMemBuffer::getData()->store.machCondLen = leng;
    memset((char *)(&SharedMemBuffer::getData()->store.machCond[0]), 0x00,
           sizeof(SharedMemBuffer::getData()->store.machCond));
    memcpy((char *)(&SharedMemBuffer::getData()->store.machCond[0]),
           (char const *)data, leng);
}

void epi_restoreDynMachineConditions(uint8_t *leng, uint8_t *data) {
    *leng = SharedMemBuffer::getDataConst()->store.machCondLen;
    memcpy((char *)data,
           (char const *)(&SharedMemBuffer::getData()->store.machCond[0]),
            *leng);
}

void gpi_storeDCbackupAccNr(uint8_t /*leng*/, uint8_t const *data) {
    // if (leng > 32) {
    //    leng = 32;
    // }
    SharedMemBuffer::getData()->store.DcBackupAccNr[0] = uchar2uint(data[1], data[0]);
    SharedMemBuffer::getData()->store.DcBackupAccNr[1] = uchar2uint(data[3], data[2]);
    SharedMemBuffer::getData()->store.DcBackupAccNr[2] = uchar2uint(data[5], data[4]);
    SharedMemBuffer::getData()->store.DcBackupAccNr[3] = uchar2uint(data[7], data[6]);
    SharedMemBuffer::getData()->store.DcBackupAccNr[4] = uchar2uint(data[9], data[8]);
    SharedMemBuffer::getData()->store.DcBackupAccNr[5] = uchar2uint(data[11], data[10]);
    SharedMemBuffer::getData()->store.DcBackupAccNr[6] = uchar2uint(data[13], data[12]);
    SharedMemBuffer::getData()->store.DcBackupAccNr[7] = uchar2uint(data[15], data[14]);
    SharedMemBuffer::getData()->store.DcBackupNrOfAccNr = 8;
}

void epi_restoreDCbackupAccNr(uint8_t *leng, uint16_t *accNrs) {
    // return accNrs[0..7]
    *leng = SharedMemBuffer::getDataConst()->store.DcBackupNrOfAccNr;
    for (int nn=0; nn<8; nn++) {
        accNrs[nn] = SharedMemBuffer::getDataConst()->store.DcBackupAccNr[nn];
    }
}

void epi_iniVRstorage(void) {
    memset((char *)(&SharedMemBuffer::getData()->store.vaultrecord[0]), 0x00,
           sizeof(SharedMemBuffer::getData()->store.vaultrecord));
    SharedMemBuffer::getData()->store.gotNrBlocksOfVaultRec = 0;
}

void gpi_storeVaultRecord(uint8_t blkNr, uint8_t const *data) {
    uint16_t start = blkNr;

        // setze pro Block ein bit, wir brauchen block 0...4
        // also muss store_gotNrBlocksOfVaultRec auf 0x1F stehen
    SharedMemBuffer::getData()->store.gotNrBlocksOfVaultRec |= (1<<start);

    start <<= 6;

    for (int ii=0; ii<64; ii++) {
        SharedMemBuffer::getData()->store.vaultrecord[start+ii] = data[ii];
    }
}

bool epi_checkIfVaultRecordAvailable(void) {
    return SharedMemBuffer::getDataConst()->store.gotNrBlocksOfVaultRec == 0x1F;
}

bool epi_restoreVaultRecord(uint16_t *length, uint8_t *buf) {
    *length = 0;
    if (SharedMemBuffer::getDataConst()->store.gotNrBlocksOfVaultRec == 0x1F) {
        *length = 320;
        memcpy((char *)buf,
               (char const *)SharedMemBuffer::getDataConst()->store.vaultrecord,
               *length);
        return true;
    }
    return false;
}

void gpi_storeCBlevel(uint32_t amount, uint16_t nrOfCoins) {
    SharedMemBuffer::getData()->store.amount = amount;
    SharedMemBuffer::getData()->store.nrOfCoins = nrOfCoins;
}

uint32_t epi_getCashBoxContent(void) {
    return SharedMemBuffer::getDataConst()->store.amount;
}

uint16_t epi_getNrOfCoinsInCashBox(void) {
    return SharedMemBuffer::getDataConst()->store.nrOfCoins;
}





void gpi_storeDcDataValid(bool isVal)
{
    SharedMemBuffer::getData()->store.dcDataValid = isVal;
}


bool gpi_areDcDataValid()
{
    return SharedMemBuffer::getDataConst()->store.dcDataValid;
}







