/*
 * ADBMS_LL_Driver.h
 *
 *  Created on: 05.06.2022
 *      Author: max
 */

#ifndef ADBMS_LL_DRIVER_H_
#define ADBMS_LL_DRIVER_H_

#include "config_ADBMS6830.h"
#include <stdint.h>


uint8_t adbmsDriverInit(SPI_HandleTypeDef* hspi);

//2 command + 2 PEC + (data + 2 DPEC) per BMS
#define CMD_BUFFER_SIZE(datalen) (4 + (N_BMS * ((datalen) + 2)))

#define BUFFER_BMS_OFFSET(bms, datalen) (4 + ((bms) * ((datalen) + 2)))

#define CMD_EMPTY_BUFFER ((uint8_t[CMD_BUFFER_SIZE(0)]){0})
#define CMD_EMPTY_BUFFER_SIZE CMD_BUFFER_SIZE(0)

HAL_StatusTypeDef ___writeCMD(uint16_t command, uint8_t * args, size_t arglen);

[[gnu::access(read_write, 2, 4), gnu::nonnull(2), gnu::always_inline]] //add dummy size variable for bounds checking, should be optimized out
static inline HAL_StatusTypeDef __writeCMD(uint16_t command, uint8_t * args, size_t arglen, size_t) {
  return ___writeCMD(command, args, arglen);
}

#define writeCMD(command, args, arglen) \
  __writeCMD(command, args, arglen, CMD_BUFFER_SIZE(arglen))

HAL_StatusTypeDef ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen);

[[gnu::access(read_write, 2, 4), gnu::nonnull(2), gnu::always_inline]] //add dummy size variable for bounds checking, should be optimized out
static inline HAL_StatusTypeDef __readCMD(uint16_t command, uint8_t * buffer, size_t arglen, size_t) {
  return ___readCMD(command, buffer, arglen);
}

#define readCMD(command, buffer, buflen) \
  __readCMD(command, buffer, buflen, CMD_BUFFER_SIZE(buflen))

HAL_StatusTypeDef __pollCMD(uint16_t command, uint8_t waitTime);

#define pollCMD(command) \
  __pollCMD(command, (N_BMS * 2) + 1) //poll is only valid after 2 * N_BMS clock cycles, +1 for safety, see datasheet page 55

uint8_t wakeUpCmd();
static inline void mcuDelay(uint16_t delay) { HAL_Delay(delay); };

#endif /* ADBMS_LL_DRIVER_H_ */
