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

Fwxv 255 moved I2C to PCA #257

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
3 changes: 3 additions & 0 deletions libraries/ms-drivers/inc/pca9555_gpio_expander.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,6 @@ StatusCode pca9555_gpio_get_state(const Pca9555GpioAddress *address, Pca9555Gpio
// as the interrupt is reset when the data is read from the port that generated the interrupt
StatusCode pca9555_gpio_subscribe_interrupts(const GpioAddress *interrupt_pin, Event event,
Task *task, void *context);

// Reads both of the PCA9555 8-bit registers, and returns a 16-bit value with all the pin stats.
StatusCode pca9555_get_register_state(I2CAddress addr, uint16_t *reg_val);
20 changes: 20 additions & 0 deletions libraries/ms-drivers/src/pca9555_gpio_expander.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,23 @@ StatusCode pca9555_gpio_subscribe_interrupts(const GpioAddress *interrupt_pin, E
gpio_it_register_interrupt(interrupt_pin, &interrupt_settings, event, task);
return STATUS_CODE_OK;
}

StatusCode pca9555_get_register_state(I2CAddress addr, uint16_t *reg_val) {
if (addr >= NUM_I2C_PORTS) {
return status_msg(STATUS_CODE_INVALID_ARGS, "Invalid PCA9555 port.");
}
uint8_t reg_arr[2] = {}; // store read value
uint8_t reg_to_read = INPUT0; // read the first register
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is INPUT0 and INPUT1? Can't seem to find them.
But basically you'll always only read and write 1 byte?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to find at what address the PCA9555 registers are at, but I couldn't find them so I assumed it was INPUT0 and INPUT1. Do you know where I should be reading from?
Yeah, essentially the function will read and write one byte for both registers and output them as a 16-bit int.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the datasheet pg 19, it should be there

status_ok_or_return(i2c_write(s_i2c_port, addr, &reg_to_read, sizeof(INPUT0)));
status_ok_or_return(
i2c_read(s_i2c_port, addr, &reg_arr[0], sizeof(reg_to_read))); // store value in reg_arr

reg_to_read = INPUT1; // read the second register
status_ok_or_return(i2c_write(s_i2c_port, addr, &reg_to_read, sizeof(INPUT1)));
status_ok_or_return(i2c_read(s_i2c_port, addr, &reg_arr[1], sizeof(reg_to_read)));

*reg_val = (reg_arr[0] << 8) +
reg_arr[1]; // return the 16-bit value with the first register as the 8 leftmost bits

return STATUS_CODE_OK;
}
7 changes: 5 additions & 2 deletions projects/centre_console/src/cc_buttons.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ static Task *cc_notify_task = NULL;
StatusCode get_button_press(void) {
// TODO: Migrate this read to PCA9555
uint16_t pca9555_reg_val = 0;
i2c_read_reg(I2C_PORT_1, PCA9555_I2C_ADDR, INPUT0, (uint8_t *)&pca9555_reg_val, 2);

// i2c_read_reg(I2C_PORT_1, PCA9555_I2C_ADDR, INPUT0, (uint8_t *)&pca9555_reg_val, 2);
// same functionality as i2c_read_reg, reads both PCA9555 registers and outputs them as a 16-bit
// value leftmost 8 bits are the pin values at INPUT0, rightmost 8 bits are the pin values at
// INPUT 1
status_ok_or_return(pca9555_get_register_state(PCA9555_I2C_ADDR, &pca9555_reg_val));
if (pca9555_reg_val == PCA9555_REG_DEFAULT) { // No button pressed
return STATUS_CODE_OK;
}
Expand Down
16 changes: 16 additions & 0 deletions projects/gpio_leds/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably get rid of this folder

General guidelines
These are just guidelines, not strict rules - document however seems best.
A README for a firmware-only project (e.g. Babydriver, MPXE, bootloader, CAN explorer) should answer the following questions:
- What is it?
- What problem does it solve?
- How do I use it? (with usage examples / example commands, etc)
- How does it work? (architectural overview)
A README for a board project (powering a hardware board, e.g. power distribution, centre console, charger, BMS carrier) should answer the following questions:
- What is the purpose of the board?
- What are all the things that the firmware needs to do?
- How does it fit into the overall system?
- How does it work? (architectural overview, e.g. what each module's purpose is or how data flows through the firmware)
-->
# gpio_leds

6 changes: 6 additions & 0 deletions projects/gpio_leds/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"libs": [
"FreeRTOS",
"ms-common"
]
}
64 changes: 64 additions & 0 deletions projects/gpio_leds/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <stdbool.h>

#include "delay.h"
#include "gpio.h"
#include "gpio_it.h"
#include "interrupt.h"
#include "log.h"
#include "misc.h"
#include "tasks.h"

Event BTN_INT_EVENT = 5;
GpioAddress addr1 = { .port = GPIO_PORT_B, .pin = 5 };
GpioAddress addr2 = { .port = GPIO_PORT_B, .pin = 4 };
GpioAddress addr3 = { .port = GPIO_PORT_B, .pin = 3 };
GpioAddress addr4 = { .port = GPIO_PORT_A, .pin = 15 };
GpioAddress addr5 = { // button
.port = GPIO_PORT_A,
.pin = 7
};

InterruptSettings settings = { .type = INTERRUPT_TYPE_INTERRUPT,
.priority = INTERRUPT_PRIORITY_NORMAL,
.edge = INTERRUPT_EDGE_RISING };
TASK(GPIO_LED, TASK_STACK_512) {
gpio_init_pin(&addr1, GPIO_OUTPUT_PUSH_PULL, GPIO_STATE_HIGH);
gpio_init_pin(&addr2, GPIO_OUTPUT_PUSH_PULL, GPIO_STATE_HIGH);
gpio_init_pin(&addr3, GPIO_OUTPUT_PUSH_PULL, GPIO_STATE_HIGH);
gpio_init_pin(&addr4, GPIO_OUTPUT_PUSH_PULL, GPIO_STATE_HIGH);
gpio_init_pin(&addr5, GPIO_INPUT_PULL_DOWN, GPIO_STATE_LOW);

while (true) {
uint32_t notification;

notify_get(&notification);
if (notify_check_event(&notification, BTN_INT_EVENT)) {
gpio_toggle_state(&addr1);
delay_ms(1000);
gpio_toggle_state(&addr2);
delay_ms(1000);
gpio_toggle_state(&addr3);
delay_ms(1000);
gpio_toggle_state(&addr4);
delay_ms(1000);
}
}
}
void run_slow_cycle() {
gpio_it_trigger_interrupt(&addr5);
}
int main(void) {
interrupt_init();

gpio_it_register_interrupt(&addr5, &settings, BTN_INT_EVENT, GPIO_LED);
gpio_init();
tasks_init();
log_init();

// tasks_init_task(leds_task, TASK_PRIORITY(2), NULL);

tasks_start();
LOG_DEBUG("Blinking LEDs...\n");

return 0;
}