#include <errno.h>
#include <SPI.h>
/* Common Frame Size */
#define MAX149X6_FRAME_SIZE 2
#define CS 10
/* Common Registers */
#define MAX149X6_CHIP_ADDR_MASK NO_OS_GENMASK(7, 6)
#define MAX149X6_ADDR_MASK NO_OS_GENMASK(4, 1)
#define MAX149X6_RW_MASK NO_OS_BIT(0)
struct max149x6_init_param {
uint32_t chip_address = 0;
uint8_t cs_pin = 10;
uint8_t en_pin;
uint8_t fault_pin;
uint8_t ready_pin;
uint8_t synch_pin;
bool crc_en;
};
/**
* @brief Device descriptor for MAX149X6.
*/
struct max149x6_desc {
uint32_t chip_address = 0;
uint8_t cs_pin = 10;
uint8_t en_pin;
uint8_t fault_pin;
uint8_t ready_pin;
uint8_t synch_pin;
uint8_t buff[MAX149X6_FRAME_SIZE + 1];
bool crc_en;
};
#define MAX14906_CHANNELS 4
#define MAX14906_SETOUT_REG 0x0
#define MAX14906_SETLED_REG 0x1
#define MAX14906_DOILEVEL_REG 0x2
#define MAX14906_INT_REG 0x3
#define MAX14906_OVR_LD_REG 0x4
#define MAX14906_OPN_WIR_FLT_REG 0x5
#define MAX14906_SHD_VDD_FLT_REG 0x6
#define MAX14906_GLOBAL_FLT_REG 0x7
#define MAX14906_CONFIG1_REG 0xA
#define MAX14906_CONFIG2_REG 0xB
#define MAX14906_CONFIG_DI_REG 0xC
#define MAX14906_CONFIG_DO_REG 0xD
#define MAX14906_CONFIG_CURR_LIM 0xE
#define MAX14906_CONFIG_MASK 0xF
/* DoiLevel register */
#define MAX14906_DOI_LEVEL_MASK(x) (1 << (x))
/* SetOUT register */
#define MAX14906_HIGHO_MASK(x) (1 << (x))
#define MAX14906_DO_MASK(x) ((3 << (2 * (x))))
#define MAX14906_CH_DIR_MASK(x) (1 << ((x) + 4))
#define MAX14906_CH(x) (x)
#define MAX14906_IEC_TYPE_MASK (1 << 7)
#define MAX14906_CL_MASK(x) ((3 << (2 * (x))))
enum max14906_iec_type {
MAX14906_TYPE_1_3,
MAX14906_TYPE_2,
};
/**
* @brief Channel configuration options.
*/
enum max14906_function {
MAX14906_OUT,
MAX14906_IN,
MAX14906_HIGH_Z
};
/**
* @brief Configuration options for the output driver (on each channel).
*/
enum max14906_do_mode {
MAX14906_HIGH_SIDE,
MAX14906_HIGH_SIDE_INRUSH,
MAX14906_PUSH_PULL_CLAMP,
MAX14906_PUSH_PULL
};
/**
* @brief Current limit options for output channels.
*/
enum max14906_climit {
MAX14906_CL_600,
MAX14906_CL_130,
MAX14906_CL_300,
MAX14906_CL_1200,
};
class Max14906 {
public:
Max14906(uint8_t csPin);
~Max14906();
int max149x6_reg_read(struct max149x6_desc *, uint32_t, uint32_t *);
/** Read the state of a channel */
int max14906_ch_get(struct max149x6_desc *, uint32_t, uint32_t *);
/** Set the state of a channel */
int max14906_ch_set(struct max149x6_desc *, uint32_t, uint32_t);
/** Configure a channel's function */
int max14906_ch_func(struct max149x6_desc *, uint32_t, enum max14906_function);
/** Configure the current limit for output channels */
int max14906_climit_set(struct max149x6_desc *, uint32_t, enum max14906_climit);
/** Read an output channel's current limit */
int max14906_climit_get(struct max149x6_desc *, uint32_t, enum max14906_climit *);
/** Initialize and configure the MAX14906 device */
int max14906_init(struct max149x6_desc **, struct max149x6_init_param *);
/** Free the resources allocated during init and place all the channels in high-z. */
int max14906_remove(struct max149x6_desc *);
private:
uint8_t csPin;
void spiWrite(uint8_t reg, uint8_t value);
uint8_t spiRead(uint8_t reg);
};
int Max14906::max14906_init(struct max149x6_desc **desc, struct max149x6_init_param *param) {
struct max149x6_desc *descriptor;
uint32_t reg_val;
int ret;
int i;
descriptor = (struct max149x6_desc *)calloc(1, sizeof(*descriptor));
if (!descriptor)
return 0;
descriptor->chip_address = param->chip_address;
descriptor->cs_pin = param->cs_pin;
descriptor->en_pin = param->en_pin;
descriptor->fault_pin = param->fault_pin;
descriptor->ready_pin = param->ready_pin;
descriptor->synch_pin = param->synch_pin;
descriptor->crc_en = param->crc_en;
pinMode(descriptor->cs_pin, OUTPUT);
digitalWrite(descriptor->cs_pin, HIGH);
pinMode(descriptor->en_pin, OUTPUT);
digitalWrite(descriptor->en_pin, HIGH);
pinMode(descriptor->fault_pin, INPUT);
pinMode(descriptor->ready_pin, INPUT);
pinMode(descriptor->synch_pin, OUTPUT);
digitalWrite(descriptor->synch_pin, HIGH);
SPI.begin();
/* Clear the latched faults generated at power up */
ret = max149x6_reg_read(descriptor, MAX14906_OVR_LD_REG, reg_val);
if (ret)
goto err;
ret = max149x6_reg_read(descriptor, MAX14906_OPN_WIR_FLT_REG, reg_val);
if (ret)
goto err;
ret = max149x6_reg_read(descriptor, MAX14906_SHD_VDD_FLT_REG, reg_val);
if (ret)
goto err;
ret = max149x6_reg_read(descriptor, MAX14906_GLOBAL_FLT_REG, reg_val);
if (ret)
goto err;
for (i = 0; i < MAX14906_CHANNELS; i++) {
ret = max14906_ch_func(descriptor, i, MAX14906_HIGH_Z);
if (ret)
goto err;
}
*desc = descriptor;
return 0;
err:
free(descriptor);
return ret;
}
/**
* @brief Free the resources allocated during init and place all the channels in high-z.
* @param desc - device descriptor for the MAX14906 that will be initialized.
* @return 0 in case of success, negative error code otherwise
*/
int Max14906::max14906_remove(struct max149x6_desc *desc) {
int ret;
int i;
if (!desc)
return 0;
for (i = 0; i < MAX14906_CHANNELS; i++) {
ret = max14906_ch_func(desc, i, MAX14906_HIGH_Z);
if (ret)
return ret;
}
SPI.end();
free(desc);
return 0;
}
/**
* @brief Write to a register over SPI
* @param reg - register address
* @param value - value to write
*/
void Max14906::spiWrite(uint8_t reg, uint8_t value) {
digitalWrite(csPin, LOW);
SPI.transfer(reg);
SPI.transfer(value);
digitalWrite(csPin, HIGH);
}
/**
* @brief Read from a register over SPI
* @param reg - register address
* @return value read from the register
*/
uint8_t Max14906::spiRead(uint8_t reg) {
digitalWrite(csPin, LOW);
SPI.transfer(reg);
uint8_t value = SPI.transfer(0x00);
digitalWrite(csPin, HIGH);
return value;
}
struct max149x6_desc *max14906;
struct max149x6_init_param max14906_ip; // Changed from pointer to structure
Max14906 Max14906(CS);
void setup() {
char msg[] = "FEI Dev";
Serial.begin(115200);
pinMode(CS, OUTPUT);
// SPI Transaction: sends the contents of buffer, and overwrites it with the received data.
digitalWrite(CS, LOW);
SPI.begin();
SPI.transfer(msg);
SPI.end();
digitalWrite(CS, HIGH);
Serial.println("Data received from eSPI device:");
Serial.println(msg);
int ret = Max14906.max14906_init(&max14906, &max14906_ip); // Pass the address of the structure
if (ret) {
Serial.println("MAX14906 Initialization Failed");
}
}
void loop() {
// Your loop code here
}