/** * Main TWI handler */ void twi_handler(void) { struct ucinfo_t *info = &ucinfo; if (ts_rx_valid == true) { /* I must be a slave, I've received something */ switch (slave_rx_addr) { case TWICMD_POWERUP: /* * Turn on a the power supply. If I'm getting this command, I'm a * slave and I must have standby power on, so there must be a power * supply on me. Separating this and TWICMD_STARTUP gets power to * ALL slaves, even those without power supplies, for when the * TWICMD_STARTUP happens. */ info->addressing_complete = false; gpio_set_pin_high(SPARE_DOWN); gpio_set_pin_high(HAVE_USB); power_supply_on(); break; case TWICMD_STARTUP: /* restart addressing cycle */ info->addressing_complete = false; gpio_set_pin_high(SPARE_DOWN); gpio_set_pin_high(HAVE_USB); usb_powerup_request(); break; case TWICMD_POWERDOWN: usb_powerdown_request(); break; case TWICMD_ADDRESS: if (tmp1 < sizeof(addresses) / sizeof(addresses[0])) { addresses[tmp1] = slave_rx_data.b[0]; su_pin[tmp1] = gpio_pin_is_high(SPARE_UP); sd_pin[tmp1] = gpio_pin_is_high(SPARE_DOWN); tmp1++; } if (gpio_pin_is_low(SPARE_UP) && gpio_pin_is_high(SPARE_DOWN)) { /* This is MY address! Grab it. */ my_twi_address = slave_rx_data.b[0]; my_twi_address_set = true; delay_msec(1); twi_slave_setup(my_twi_address); delay_msec(1); if (info->chain_configuration == CC_OPEN_UP) { /* * Send notification back up chain to master. * Last address done */ gpio_set_pin_low(HAVE_USB); } else { /* Propagate down so next module gets next address. */ gpio_set_pin_low(SPARE_DOWN); } } break; case TWICMD_ADDRESSING_COMPLETE: info->addressing_complete = true; gpio_set_pin_high(SPARE_DOWN); gpio_set_pin_high(HAVE_USB); break; case TWICMD_FPGA_ASIC_CTL: fpga_reg_write(FA_ASIC_CONTROL, (slave_rx_data.b[0] & F_FORCE_BAUD) ? (slave_rx_data.b[0] & ~F_FORCE_BAUD) : ((slave_rx_data.b[0] & ~F_ASIC_BAUD_MASK) | ucinfo.asic_baud_rate_code)); break; case TWICMD_REBOOT: if (slave_rx_nb && slave_rx_data.b[0]) { /* * Tell Atmel DFU loader not to start app ever again (harmless * with custom loader). */ flashc_erase_gp_fuse_bit(31, true); flashc_write_gp_fuse_bit(31, true); /* * Tell custom bootloader not to start app on this boot * (harmless with Atmel DFU loader). */ AVR32_PM.gplp[1] = 0x73746179; } /* never returns */ self_reset(); break; case TWICMD_FAN_SET: set_fan_speed(slave_rx_data.b[0], slave_rx_data.b[1]); break; case TWICMD_DIE_SETTINGS: if (slave_rx_nb) { hf_nvram_write_die_settings(0, &slave_rx_data.opSettings); } break; case TWICMD_BAD_CORE_BITMAP: if (slave_rx_nb) { hf_nvram_write_bad_core_bitmap(0, (((uint16_t) slave_rx_data.b[0]) << 8) | slave_rx_data.b[1]); } break; case TWICMD_MIXED_BAUD: set_mixed_slave_baudrate(); break; case TWICMD_VOLTAGE_SET: if (slave_rx_nb >= 3) { module_voltage_set(0, slave_rx_data.b[0], ((uint16_t) slave_rx_data.b[1] << 8) | slave_rx_data.b[2]); } break; default: break; } ts_rx_valid = false; } if (info->master == false) { if (info->addressing_complete == false) { /* propagate HAVE_USB back up chain to master during address cycle */ if (info->chain_configuration == CC_MIDDLE) { if (gpio_pin_is_high(USB_DOWN)) { gpio_set_pin_high(HAVE_USB); } else { gpio_set_pin_low(HAVE_USB); } } } } masterHandler(); }
//! \brief Initialise l'i2c. void i2cInit(void) { twi_slave_options_t twi_slave_options; twi_slave_setup(&I2C_TWI, &twi_slave_options, &_twiSlave, &_twiHandler, I2C_ADD, TWI_SLAVE_INTLVL_LO_gc); }