#include #include "hardware/gpio.h" #include "hardware/i2c.h" #include "pico/stdlib.h" #include "pico/binary_info.h" #include "pico/i2c_slave.h" const uint PIN_DIGIT_BASE = 18; const uint PIN_SEGMENT_BASE = 2; const uint N_DIGITS = 4; const uint I2C_PIN_SDA = 0; const uint I2C_PIN_SCL = 1; const uint I2C_SLAVE_ADDRESS = 0x17; const uint I2C_RATE = 100 * 1000; uint8_t digit_states[4] = { 0 }; static struct { bool digit_written; uint digit; } i2c_context; static void write_digit(uint8_t digit) { const uint mask = (0xffffffff << PIN_SEGMENT_BASE) ^ (0xffffffff << PIN_SEGMENT_BASE + 8); gpio_put_masked(mask, (~digit & 0xff) << PIN_SEGMENT_BASE); gpio_put_masked(mask, digit << PIN_SEGMENT_BASE); } static void setup_io() { for (uint i = PIN_DIGIT_BASE; i < PIN_DIGIT_BASE + N_DIGITS; i++) { gpio_init(i); gpio_set_dir(i, GPIO_OUT); gpio_put(i, 0); } for (uint i = PIN_SEGMENT_BASE; i < PIN_SEGMENT_BASE + 8; i++) { gpio_init(i); gpio_set_dir(i, GPIO_OUT); } write_digit(0); } static void display_loop() { for (uint i = 0; i < N_DIGITS; i++) { uint prev = i == 0 ? N_DIGITS - 1 : i - 1; gpio_put(PIN_DIGIT_BASE + prev, 0); sleep_us(100); write_digit(digit_states[i]); gpio_put(PIN_DIGIT_BASE + i, 1); sleep_ms(1); } } static void i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) { switch (event) { case I2C_SLAVE_RECEIVE: // master has written some data if (!i2c_context.digit_written) { // writes always start with the memory address uint8_t addr = i2c_read_byte_raw(i2c); i2c_context.digit = addr < N_DIGITS ? addr : -1; i2c_context.digit_written = true; } else if (i2c_context.digit != -1) { // save into memory digit_states[i2c_context.digit] = i2c_read_byte_raw(i2c); } break; case I2C_SLAVE_REQUEST: // master is requesting data // load from memory uint8_t data = i2c_context.digit != -1 ? digit_states[i2c_context.digit] : 0; i2c_write_byte_raw(i2c, data); break; case I2C_SLAVE_FINISH: // master has signalled Stop / Restart i2c_context.digit_written = false; break; default: break; } } static void setup_i2c() { gpio_init(I2C_PIN_SDA); gpio_set_function(I2C_PIN_SDA, GPIO_FUNC_I2C); gpio_pull_up(I2C_PIN_SDA); gpio_init(I2C_PIN_SCL); gpio_set_function(I2C_PIN_SCL, GPIO_FUNC_I2C); gpio_pull_up(I2C_PIN_SCL); i2c_init(i2c0, I2C_RATE); // configure I2C0 for slave mode i2c_slave_init(i2c0, I2C_SLAVE_ADDRESS, &i2c_slave_handler); } int main() { bi_decl(bi_program_description("qCLK driver.")); stdio_init_all(); setup_io(); setup_i2c(); while (1) display_loop(); }