/***** * * Le principe est que la télécommande soit l'esclave I2C * Pour envoyer un message, on charge le message à l'adresse 0 de la "mémoire" pour l'i2c * * Pour lire le message, le robot interroge la télécommande, et demande le contenu à partir de l'adresse 0 de la mémoire. * Ainsi, en cas d'échec de la communication, le robot détectera une manette débranchée. * Par défaut, la fonction lit 255 caractères. * * Copyright (c) 2024 - Club robotique de Riom * * * SPDX-License-Identifier: BSD-3-Clause */ #include "i2c_fifo.h" #include "i2c_slave.h" #include "i2c_maitre.h" #include "string.h" /// DEBUT DE LA CONFIGURATION de L'I2C #define I2C0_SDA_PIN 16 #define I2C0_SCL_PIN 17 #define I2C_SLAVE_ADDRESS 0x17 static const uint I2C_SLAVE_SDA_PIN = I2C0_SDA_PIN; static const uint I2C_SLAVE_SCL_PIN = I2C0_SCL_PIN; // The slave implements a 256 byte memory. To write a series of bytes, the master first // writes the memory address, followed by the data. The address is automatically incremented // for each byte transferred, looping back to 0 upon reaching the end. Reading is done // sequentially from the current memory address. static struct { uint8_t mem[256]; uint8_t mem_address; bool mem_address_written; } context; // Our handler is called from the I2C ISR, so it must complete quickly. Blocking calls / // printing to stdio may interfere with interrupt handling. 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 (!context.mem_address_written) { // writes always start with the memory address context.mem_address = i2c_read_byte(i2c); context.mem_address_written = true; } else { // save into memory context.mem[context.mem_address] = i2c_read_byte(i2c); context.mem_address++; } break; case I2C_SLAVE_REQUEST: // master is requesting data // load from memory i2c_write_byte(i2c, context.mem[context.mem_address]); context.mem_address++; break; case I2C_SLAVE_FINISH: // master has signalled Stop / Restart context.mem_address_written = false; break; default: break; } } void i2c_set_slave_mode_perso(i2c_inst_t *i2c, uint8_t addr) { i2c->hw->enable = 0; //while( !(i2c->hw->enable_status & 0x1) ); i2c->hw->sar = addr; i2c->hw->con = 0; i2c->hw->enable = 1; } static void setup_slave() { gpio_init(I2C_SLAVE_SDA_PIN); gpio_set_function(I2C_SLAVE_SDA_PIN, GPIO_FUNC_I2C); gpio_pull_up(I2C_SLAVE_SDA_PIN); gpio_init(I2C_SLAVE_SCL_PIN); gpio_set_function(I2C_SLAVE_SCL_PIN, GPIO_FUNC_I2C); gpio_pull_up(I2C_SLAVE_SCL_PIN); i2c_slave_init(i2c0, I2C_SLAVE_ADDRESS, &i2c_slave_handler); } /// FIN DE LA CONFIGURATION de L'I2C void communication_init(void){ setup_slave(); i2c_maitre_init(); } void communication_envoyer_message(unsigned char * message, unsigned int message_length){ memcpy(context.mem, message, message_length); } int communication_lire_message(unsigned char * message){ i2c_lire_registre(I2C_SLAVE_ADDRESS, 0, message, 255); }