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

/*
 * fpgaMem.h
 *
 *  Created on: 04.04.2022
 *      Author: preitinger
 */

#ifndef FPGASERIAL_FPGAMEM_H_
#define FPGASERIAL_FPGAMEM_H_

#include "../KM_DmaChan_MappedIo.h"
#include "../dmaFramework/dmaAddresses.h"
#include "../KM_FpgaAddresses.h"

static DmaChan_MappedIo fpgaMappedIo;

static int fpgaMem_init(void) {
    int res;

    res = DmaChan_MappedIo_create(&fpgaMappedIo, FPGA_ADDR_BASE, FPGA_ADDR_SIZE);
    pr_info("fpgaMem_init: &fpgaMappedIo created mit res=%d\n", res);

    if (res) {
        goto err_mappedIo_create;
    }

    return 0;

    err_mappedIo_create:
    return res;
}

static void fpgaMem_exit(void) {
    DmaChan_MappedIo_delete(&fpgaMappedIo);
}

/**
 * Macht aus einer Adresse zum RAM ram_km (siehe fpgaRamKmAddresses.h)
 * eine Adresse relativ zu FPGA_ADDR_BASE, die z.B. fuer
 * DmaChan_MappedIo_set16(&fpgaMappedIo, addr, data) verwendet werden kann
 */
static unsigned long fpgaWriteAddrOfRamKmAddr(off_t addrInRamKm) {
    return ADDR_RAM_KM | (addrInRamKm << 1);
}

static unsigned long fpgaReadAddrOfRamKmAddr(off_t addrInRamKm) {
    return ADDR_READ_KM | (addrInRamKm << 1);
}

static void ramKmWrite16(off_t addrInRamKm, uint16_t data) {
    DmaChan_MappedIo_set16(&fpgaMappedIo, fpgaWriteAddrOfRamKmAddr(addrInRamKm), data);
}

static uint16_t ramKmRead16(off_t addrInRamKm) {
    return DmaChan_MappedIo_get16(&fpgaMappedIo, fpgaReadAddrOfRamKmAddr(addrInRamKm));
}

static void ramKmWrite32(off_t addrInRamKm, uint32_t data) {
    DmaChan_MappedIo_set32(&fpgaMappedIo, fpgaWriteAddrOfRamKmAddr(addrInRamKm), data);
}

/**
 * kopiert den Inhalt des Arrays ab data der Laenge count nach ram_km[addrInRamKm], ram_km[addrInRamKm+1], ...
 * count: Anzahl Bytes, muss gerade sein
 */
static void ramKmWrite(off_t addrInRamKm, const void* data, size_t count) {
    ASSERT((count & 1) == 0);

    DmaChan_MappedIo_set(&fpgaMappedIo, fpgaWriteAddrOfRamKmAddr(addrInRamKm), data, count);
}

static void ramKmRead(off_t addrInRamKm, void* to, size_t count) __attribute((unused));

static void ramKmRead(off_t addrInRamKm, void* to, size_t count) {
    DmaChan_MappedIo_get(&fpgaMappedIo, fpgaReadAddrOfRamKmAddr(addrInRamKm), to, count);
}

#endif /* FPGASERIAL_FPGAMEM_H_ */
