Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAX7314 GPIO expander #106

Merged
merged 3 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions general/include/max7314.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

typedef enum {
MAX7314_PINS_0_TO_7 = 0,
MAX7314_PINS_8_TO_15 = 1,
MAX7314_ALL_PINS = 2
MAX7314_PINS_8_TO_15 = 1
} max7314_pin_regs_t;

typedef enum {
Expand Down Expand Up @@ -42,14 +41,19 @@ HAL_StatusTypeDef max7314_set_pin_mode(max7314_t *max, uint8_t pin, max7314_pin_

HAL_StatusTypeDef max7314_set_pin_modes(max7314_t *max, max7314_pin_regs_t reg, uint8_t *pin_configs);

/**
* @brief Read an input pin
*/
HAL_StatusTypeDef max7314_read_pin(max7314_t *max, uint8_t pin, bool *state);

/**
* @brief Turn an output pin on or off
*/
HAL_StatusTypeDef max7314_set_pin_state(max7314_t *max, uint16_t pin, bool state);
HAL_StatusTypeDef max7314_set_pin_state(max7314_t *max, uint8_t pin, bool state);

/**
* @brief Read the state of an output pin
*/
HAL_StatusTypeDef max7314_read_pin_state(max7314_t *max, uint16_t pin, bool* state);
HAL_StatusTypeDef max7314_read_pin_state(max7314_t *max, uint8_t pin, bool* state);

#endif // MAX7314_H
#endif // MAX7314_H
111 changes: 54 additions & 57 deletions general/src/max7314.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
#define MAX7314_CONFIG_REG 0x0F
#define FIRST_OUTPUT_REGISTER 0x10

#define REG_SIZE 1
#define REG_SIZE 1 //byte
#define TIMEOUT 2000


HAL_StatusTypeDef read_reg(max7314_t *max, uint16_t address, uint8_t *data) {
return HAL_I2C_Mem_Read(max->i2c_handle, max->dev_addr, address, I2C_MEMADD_SIZE_8BIT, data, REG_SIZE, TIMEOUT);
}
Expand All @@ -21,18 +20,15 @@ HAL_StatusTypeDef write_reg(max7314_t *max, uint16_t address, uint8_t *data) {

HAL_StatusTypeDef max7314_init(max7314_t *max, I2C_HandleTypeDef *i2c_handle) {
max->i2c_handle = i2c_handle;
max->dev_addr = max->dev_addr << 1u; /* shifted one to the left cuz STM says so */

/* Check to see if i2c is working */
uint8_t data[1];
HAL_StatusTypeDef status = read_reg(max, MAX7314_CONFIG_REG, data);
if (status != HAL_OK)
return status;
max->dev_addr = max->dev_addr << 1u ; /* shifted one to the left cuz STM says so */

if (data[0] != 0b00001100) /* configuration register startup state */
uint8_t config_data = 0b01001100;
HAL_StatusTypeDef status = max7314_write_config(max, &config_data);
if (status != HAL_OK) {
return HAL_ERROR;
}

return status;
return HAL_OK;
}

HAL_StatusTypeDef max7314_write_config(max7314_t *max, uint8_t *config) {
Expand All @@ -41,31 +37,29 @@ HAL_StatusTypeDef max7314_write_config(max7314_t *max, uint8_t *config) {

HAL_StatusTypeDef max7314_set_pin_mode(max7314_t *max, uint8_t pin, max7314_pin_modes_t mode)
{
uint8_t conf_data[1];
uint8_t conf_data;
HAL_StatusTypeDef status;

if (pin < 8) {
if (pin < 7) {
/* Read current port configuration */
status = read_reg(max, MAX7314_PORT_CONFIG_0_TO_7, conf_data);
status = read_reg(max, MAX7314_PORT_CONFIG_0_TO_7, &conf_data);
if (status != HAL_OK)
return status;

/* Change port configuration of desired pin */
uint8_t mask = 1 << pin;
conf_data[0] = ((conf_data[0] & ~mask) | (mode << pin)); // set bit to specific value
status = write_reg(max, MAX7314_PORT_CONFIG_0_TO_7, conf_data);
/* Change port configuration of desired pin. Bit manip sets one bit to mode. */
conf_data = (conf_data & ~(1u << pin)) | (mode << pin);
status = write_reg(max, MAX7314_PORT_CONFIG_0_TO_7, &conf_data);
if (status != HAL_OK)
return status;

} else {
/* Same as above but for different register */
status = read_reg(max, MAX7314_PORT_CONFIG_8_TO_15, conf_data);
status = read_reg(max, MAX7314_PORT_CONFIG_8_TO_15, &conf_data);
if (status != HAL_OK)
return status;

uint8_t mask = 1 << pin;
conf_data[0] = ((conf_data[0] & ~mask) | (mode << pin)); // set
status = write_reg(max, MAX7314_PORT_CONFIG_8_TO_15, conf_data);
conf_data = (conf_data & ~(1u << (pin - REG_SIZE))) | (mode << (pin - REG_SIZE));
status = write_reg(max, MAX7314_PORT_CONFIG_8_TO_15, &conf_data);
if (status != HAL_OK)
return status;
}
Expand All @@ -75,69 +69,72 @@ HAL_StatusTypeDef max7314_set_pin_mode(max7314_t *max, uint8_t pin, max7314_pin_

HAL_StatusTypeDef max7314_set_pin_modes(max7314_t *max, max7314_pin_regs_t reg, uint8_t *pin_configs)
{
return write_reg(max, MAX7314_PORT_CONFIG_0_TO_7 + reg, pin_configs);
}

HAL_StatusTypeDef max7314_read_pin(max7314_t *max, uint8_t pin, bool *state)
{
uint8_t pin_data;
HAL_StatusTypeDef status;

if (reg < 2) {
/* Set pin modes of one register */
status = write_reg(max, MAX7314_PORT_CONFIG_0_TO_7 + reg, pin_configs);
if (pin < 8) {
/* similar to set_pin_mode */
status = read_reg(max, MAX7314_INPUT_PORTS_0_TO_7, &pin_data);
if (status != HAL_OK)
return status;

*state = pin_data & (1u << pin);
} else {
/* Set pin modes of both registers. pin_configs should have 16 elements in this case */
status = write_reg(max, MAX7314_PORT_CONFIG_0_TO_7, pin_configs);
status = read_reg(max, MAX7314_INPUT_PORTS_8_TO_15, &pin_data);
if (status != HAL_OK)
return status;

*state = pin_data & (1u << (pin - REG_SIZE));
}

return HAL_OK;
}

HAL_StatusTypeDef max7314_set_pin_state(max7314_t *max, uint16_t pin, bool state)
HAL_StatusTypeDef max7314_set_pin_state(max7314_t *max, uint8_t pin, bool state)
{
uint8_t pin_data[1];
uint8_t pin_data;
HAL_StatusTypeDef status;

/* 2 pins, each 4 bits, per register */
status = read_reg(max, FIRST_OUTPUT_REGISTER + (pin % 2), pin_data);
status = read_reg(max, FIRST_OUTPUT_REGISTER + (pin % 2), &pin_data);
if (status != HAL_OK)
return status;

if (pin % 2 == 0) {
pin_data[0] = state;
pin_data[1] = state;
pin_data[2] = state;
pin_data[3] = state;
/* Bit manipulation changes only the bits we want to. */
if (state) {
pin_data = (pin_data & ~(0b1111 << (pin % 2))) | (0b1111 << (pin % 2));
} else {
pin_data[4] = state;
pin_data[5] = state;
pin_data[6] = state;
pin_data[7] = state;
pin_data = (pin_data & ~(0b0000 << (pin % 2))) | (0b0000 << (pin % 2));
}

/* Write to register containing the desired pin */
status = write_reg(max, FIRST_OUTPUT_REGISTER + (pin % 2), pin_data);
if (status != HAL_OK)
return status;
status = write_reg(max, FIRST_OUTPUT_REGISTER + (pin % 2), &pin_data);

return HAL_OK;
return status;
}

HAL_StatusTypeDef max7314_read_pin_state(max7314_t *max, uint16_t pin, bool *state)
HAL_StatusTypeDef max7314_read_pin_state(max7314_t *max, uint8_t pin, bool* state)
{
uint8_t pin_data[1];
uint8_t pin_data;
HAL_StatusTypeDef status;

status = read_reg(max, FIRST_OUTPUT_REGISTER + (pin % 2), pin_data);
if (status != HAL_OK)
if (pin < 8) {
status = read_reg(max, 0x00, &pin_data);
pin_data &= 1u << pin;
} else {
status = read_reg(max, 0x01, &pin_data);
pin_data &= 1u << (pin - REG_SIZE);
}

if (status != HAL_OK)
return status;

if (pin % 2 == 0)
pin_data[0] = pin_data[0] & ~(0b10000000 | 0b01000000 | 0b00100000 | 0b00010000);
else
pin_data[0] = pin_data[0] & ~0b00001111;

// With the other bits cleared, if the number is greater than zero, then the pin is on
*state = pin_data[0] > 0;
*state = pin_data > 0;

return HAL_OK;
}
return status;
}
Loading