Using a dual-function pin
Posted: Mon Dec 11, 2023 11:37 pm
Hi there;
I'm relatively new to embedded systems, interrupts, and especially to esp-idf, an am trying to wrap my head around something. I'm trying to write a driver for the TLV493D magnetic encoder. This encoder is - apparently - somewhat peculiar in that it communicates exclusively over I2C, but shares its SCL pin with /INT (which is to say: the sensor can send an interrupt to alert the mcu that it has data available to read).
Setting aside how difficult I think it might be to manage detecting an interrupt on a clock line with multiple peripherals, I'd like to figure out how to get it working with a single-mcu-single-sensor setup. But even then, I'm unsure how to configure this pin to be both an output for SCL and an input for INT.
I *think*, once configured, I can do something like disable the interrupt (somehow) inside the ISR, do the data read, and re-enable the interrupt. But I haven't yet made it far enough to try that algorithm because I can't quite figure out how to configure things to begin with. Might anyone have some advice? (also, I'm sure there are lots of ways to sidestep this difficulty; I'd like to learn how it can be done because, I guess, I'm stubborn and eager to learn).
Here's a snippet from the code I'm trying (guided largely by chatGPT/BARD, who really seem to struggle keeping up with the changes in various esp-idf versions. I'm using 5.1.2 currently)
I'm relatively new to embedded systems, interrupts, and especially to esp-idf, an am trying to wrap my head around something. I'm trying to write a driver for the TLV493D magnetic encoder. This encoder is - apparently - somewhat peculiar in that it communicates exclusively over I2C, but shares its SCL pin with /INT (which is to say: the sensor can send an interrupt to alert the mcu that it has data available to read).
Setting aside how difficult I think it might be to manage detecting an interrupt on a clock line with multiple peripherals, I'd like to figure out how to get it working with a single-mcu-single-sensor setup. But even then, I'm unsure how to configure this pin to be both an output for SCL and an input for INT.
I *think*, once configured, I can do something like disable the interrupt (somehow) inside the ISR, do the data read, and re-enable the interrupt. But I haven't yet made it far enough to try that algorithm because I can't quite figure out how to configure things to begin with. Might anyone have some advice? (also, I'm sure there are lots of ways to sidestep this difficulty; I'd like to learn how it can be done because, I guess, I'm stubborn and eager to learn).
Here's a snippet from the code I'm trying (guided largely by chatGPT/BARD, who really seem to struggle keeping up with the changes in various esp-idf versions. I'm using 5.1.2 currently)
Code: Select all
static void IRAM_ATTR tlv_interrupt(void *arg) {
// if we made it here we're on the right track...
}
void app_main() {
i2c_config_t conf = {
.mode = I2C_MODE_MASTER, // Configure Master mode
.sda_io_num = I2C_MASTER_SDA_IO, // SDA pin
.scl_io_num = I2C_MASTER_SCL_INT_IO, // SCL pin
.master.clk_speed = I2C_MASTER_FREQ_HZ, // Clock speed
// .sda_pullup_en = GPIO_PULLUP_ENABLE, // I bypass these because I already include
// .scl_pullup_en = GPIO_PULLUP_ENABLE, // 2.2k resistors on my breakout boards.
};
// Initialize the above configuration
i2c_param_config(I2C_MASTER_NUM,
&conf);
i2c_driver_install( I2C_MASTER_NUM,
conf.mode,
0,
0,
0
);
// doing the below seems to break communicaiton with the sensor
gpio_config_t gpio_interrupt_conf = {
.pin_bit_mask = (1ULL << I2C_MASTER_SCL_INT_IO),
.mode = GPIO_MODE_INPUT_OUTPUT_OD, // not sure what this should be
//.pull_up_en = GPIO_PULLUP_ENABLE,
.intr_type = GPIO_INTR_LOW_LEVEL,
};
gpio_config(&gpio_interrupt_conf);
gpio_isr_handler_add(I2C_MASTER_SCL_INT_IO, tlv_interrupt, NULL);
...