/***************************************************************************/
/*                             Druckersoftware                             */
/*                    Copyright (C) Carl Valentin GmbH                     */
/***************************************************************************/

/*
 * KM_uart_rx_buffer.h
 *
 *  Created on: 04.05.2022
 *      Author: preitinger
 */

#ifndef FPGASERIAL_KM_UART_RX_BUFFER_H_
#define FPGASERIAL_KM_UART_RX_BUFFER_H_

#include "../dmaFramework/dmaFramework.h"
#include "dmaPayloadKM.h"

#if 1 // Original
#define RX_SRC_CAPACITY 512 // bytes, nicht 16-Bit-Woerter
// Wie gross muss RX_DST_CAPACITY sein damit bei 1MBit/s auch ohne Paritaetsbit und mit nur einem Stop-Bit max. alle 10ms eine Uebertragung stattfinden muss?
// In 10ms werden 1000000 * 10/1000 Roh-Bits uebertragen.
// Je einem Nutzdaten-Byte werden mind. 10 Roh-Bits uebertragen, d.h. Anzahl der Nutzdaten-Bytes ist <= Anzahl der Roh-Bits / 10.
// Also max. Nutz-Bytes in 10ms: 1000000 * 10/1000 / 10 = 1000
// Waehle also mind. "runde" 1024 ;-)
// Waehle nun Linux-Seitengroesse (4KB):
#define RX_DST_CAPACITY (4*1024)
#else // weniger zum Testen
#define RX_SRC_CAPACITY 16 // bytes
#define RX_DST_CAPACITY 64
#endif

typedef struct {
    // offsets relativ zu mappedDma + mappedSize (also dem Ende des gemapten DMA-Bereichs)
    int32_t dmaOffData, dmaOffFlags;
    // Laenge fest codiert
} TUartRxBuffer;

// public:
/**
 * *dmaOffEnd ist die Position im allokierten DMA-Block, ab der die Daten fuer den erzeugten uart_rx_buffer rueckwaerts anzulegen sind.
 * Nach dem Aufruf zeigt dmaOffEnd auf das neue Ende des nun noch verfuegbaren DMA-Speicherbereichs.
 */
static int uart_rx_buffer_create(TUartRxBuffer* p,
//                                 uint32_t frkmRxData,
//                                 uint32_t frkmRxFlags,
//                                 uint32_t frkmRxPsData,
//                                 uint32_t frkmRxPsFlags,
                                 int32_t* dmaOffEnd);
static void uart_rx_buffer_destroy(TUartRxBuffer* p);

// private:

#define PRIV_UART_RX_BUFFER_FREE_PS(ps) do { if ((ps) != -1) { my_edma_free_slot(ps); ps = -1; } } while(0)

//static void priv_uart_rx_buffer_freeParamsets(TUartRxBuffer* p) {
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psRespType);
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psCopyPsData);
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psDelayData);
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psData);
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psCopyPsFlags);
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psDelayFlags);
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psFlags);
//    PRIV_UART_RX_BUFFER_FREE_PS(p->psSize);
//
//}

static int uart_rx_buffer_create(TUartRxBuffer* p,
//                                 uint32_t frkmRxData,
//                                 uint32_t frkmRxFlags,
//                                 uint32_t frkmRxPsData,
//                                 uint32_t frkmRxPsFlags,
                                 int32_t* dmaOffEnd) {

//    p->psRespType = p->psCopyPsData = p->psDelayData = p->psData = p->psCopyPsFlags = p->psDelayFlags, p->psFlags = -1, p->psSize = -1;
//
//    p->psRespType = my_edma_alloc_slot(-1);
//    p->psCopyPsData = my_edma_alloc_slot(-1);
//    p->psDelayData = my_edma_alloc_slot(-1);
//    p->psData = my_edma_alloc_slot(-1);
//    p->psCopyPsFlags = my_edma_alloc_slot(-1);
//    p->psDelayFlags = my_edma_alloc_slot(-1);
//    p->psFlags = my_edma_alloc_slot(-1);
//    p->psSize = my_edma_alloc_slot(-1);
//
//    if (p->psRespType == -1 || p->psCopyPsData == -1 || p->psDelayData == -1 || p->psData == -1 || p->psCopyPsFlags == -1 || p->psDelayFlags == -1 || p->psFlags == -1 || p->psSize == -1) {
//        priv_uart_rx_buffer_freeParamsets(p);
//        return -1;
//    }

    *dmaOffEnd -= RX_DST_CAPACITY;
    p->dmaOffData = *dmaOffEnd;

    *dmaOffEnd -= RX_DST_CAPACITY;
    p->dmaOffFlags = *dmaOffEnd;

//    // Parametersaetze initialisieren
//
//    {
//        int payloadChanNum = -1, start1ChanNum = -1;
//
//        payloadChanNum = edma_channel_num(payloadKMCh);
//        start1ChanNum = edma_channel_num(start1Chan);
//
//        { // Inhalt fuer psRespType:
//            struct edmacc_param ps = {
//                    .opt = SYNCDIM | EDMA_TCC(payloadChanNum) | TCCHEN | TCINTEN,
//                    .src = dmaReadAddrFpgaRamKm(FRKM_RESPONSE_TYPE),
//                    .a_b_cnt = COMBINE_LO_HI(2, 1),
//                    .dst = dmaBufEndAddr(mappedDma, mappedSize, DBE_RESPONSE_TYPE),
//                    .src_dst_bidx = 0,
//                    .link_bcntrld = COMBINE_LO_HI(p->psCopyPsData << 5, 0),
//                    .src_dst_cidx = 0,
//                    .ccnt = 1
//            };
//
//            my_edma_write_slot(edmaMappedIo1._a, p->psCopyPsData, &ps);
//        }
//
//        { // Inhalt fuer psCopyPsData:
//            struct edmacc_param ps = {
//                    .opt = SYNCDIM | EDMA_TCC(payloadChanNum) | TCCHEN,
//                    .src = dmaReadAddrFpgaRamKm(frkmRxPsData),
//                    .a_b_cnt = COMBINE_LO_HI(2, 16), // 1 EDMA-Parametersatz ist 32 Byte lang, also 2 * 16
//                    .dst = dmaAddrEdmaParamset(p->psData),
//                    .src_dst_bidx = 0,
//                    .link_bcntrld = COMBINE_LO_HI(p->psDelayData << 5, 0),
//                    .src_dst_cidx = 0,
//                    .ccnt = 1
//            };
//
//            my_edma_write_slot(edmaMappedIo1._a, p->psCopyPsData, &ps);
//        }
//
//        {
//            struct edmacc_param ps = {
//                    .opt = SYNCDIM | EDMA_TCC(payloadChanNum) | TCCHEN,
//                    .src = 0,
//                    .a_b_cnt = 0,
//                    .dst = 0,
//                    .src_dst_bidx = 0,
//                    .link_bcntrld = COMBINE_LO_HI(p->psData << 5, 0),
//                    .src_dst_cidx = 0,
//                    .ccnt = 1
//            };
//        }
//
//
//        // Parametersaetze im ram_km (im FPGA):
//        {
//            // Vorlage im ram_km, welche im FPGA angepasst werden kann, und dann kopiert wird
//            // auf den Parametersatz p->psData (dies ist definiert oben im psCopyPsData)
//            struct edmacc_param ps = {
//                    .opt = SYNCDIM | EDMA_TCC(payloadChanNum) | TCCHEN,
//                    .src = dmaReadAddrFpgaRamKm(frkmRxData),
//                    .a_b_cnt = COMBINE_LO_HI(2, RX_ARRAY_LEN),
//                    .dst = dmaAddrMapped(dmaAddressesEnv.mappedSize + p->dmaOffData),
//                    .src_dst_bidx = 0,
//                    .link_bcntrld = COMBINE_LO_HI(p->psCopyPsFlags << 5, 0),
//                    .src_dst_cidx = 0,
//                    .ccnt = 1
//            };
//
//            ASSERT(32 == sizeof(ps));
//            // diesen parametersatz ablegen im ram_km im fpga an ram-adresse frkmRxPsData:
//            ramKmWrite(frkmRxPsData, &ps, sizeof(ps));
//        }
//
//        // TODO
//
//        {
//            // Vorlage im ram_km, welche im FPGA angepasst werden kann, und dann kopiert wird
//            // auf den Parametersatz p->psFlags
//            struct edmacc_param ps = {
//                    // hier verlinkung zu pkmChainBackPs in dmaPayloadKM.h
//                    .opt = SYNCDIM | EDMA_TCC(payloadChanNum) | TCCHEN,
//                    .src = dmaReadAddrFpgaRamKm(frkmRxFlags),
//                    .a_b_cnt = COMBINE_LO_HI(2, RX_ARRAY_LEN),
//                    .dst = dmaAddrMapped(dmaAddressesEnv.mappedSize + p->dmaOffFlags),
//                    .src_dst_bidx = 0,
//                    .link_bcntrld = COMBINE_LO_HI(pkmChainBackPs << 5, 0),
//                    .src_dst_cidx = 0,
//                    .ccnt = 1
//            };
//
//            ASSERT(32 == sizeof(ps));
//            // diesen parametersatz ablegen im ram_km im fpga an ram-adresse frkmRxPsData:
//            ramKmWrite(frkmRxPsFlags, &ps, sizeof(ps));
//        }
//    }

    return 0;
}

static void uart_rx_buffer_destroy(TUartRxBuffer* p) {
//    priv_uart_rx_buffer_freeParamsets(p);
}


#endif /* FPGASERIAL_KM_UART_RX_BUFFER_H_ */
