static void serialInputPortActivate(softSerial_t *softSerial) { if (softSerial->port.options & SERIAL_INVERTED) { #ifdef STM32F1 IOConfigGPIO(softSerial->rxIO, IOCFG_IPD); #else IOConfigGPIO(softSerial->rxIO, IOCFG_AF_PP_PD); #endif } else { #ifdef STM32F1 IOConfigGPIO(softSerial->rxIO, IOCFG_IPU); #else IOConfigGPIO(softSerial->rxIO, IOCFG_AF_PP_UP); #endif } softSerial->rxActive = true; softSerial->isSearchingForStartBit = true; softSerial->rxBitIndex = 0; // Enable input capture #ifdef USE_HAL_DRIVER TIM_CCxChannelCmd(softSerial->timerHardware->tim, softSerial->timerHardware->channel, TIM_CCx_ENABLE); #else TIM_CCxCmd(softSerial->timerHardware->tim, softSerial->timerHardware->channel, TIM_CCx_Enable); #endif }
static void serialInputPortActivate(softSerial_t *softSerial) { if (softSerial->port.options & SERIAL_INVERTED) { #ifdef STM32F1 IOConfigGPIO(softSerial->rxIO, IOCFG_IPD); #elif defined(STM32F7) IOConfigGPIOAF(softSerial->rxIO, IOCFG_AF_PP_PD, softSerial->timerHardware->alternateFunction); #else IOConfigGPIO(softSerial->rxIO, IOCFG_AF_PP_PD); #endif } else { #ifdef STM32F1 IOConfigGPIO(softSerial->rxIO, IOCFG_IPU); #elif defined(STM32F7) IOConfigGPIOAF(softSerial->rxIO, IOCFG_AF_PP_UP, softSerial->timerHardware->alternateFunction); #else IOConfigGPIO(softSerial->rxIO, IOCFG_AF_PP_UP); #endif } softSerial->rxActive = true; softSerial->isSearchingForStartBit = true; softSerial->rxBitIndex = 0; // Enable input capture serialEnableCC(softSerial); }
static void i2cUnstick(IO_t scl, IO_t sda) { int i; int timeout = 100; IOHi(scl); IOHi(sda); IOConfigGPIO(scl, IOCFG_OUT_OD); IOConfigGPIO(sda, IOCFG_OUT_OD); for (i = 0; i < 8; i++) { // Wait for any clock stretching to finish while (!IORead(scl) && timeout) { delayMicroseconds(10); timeout--; } // Pull low IOLo(scl); // Set bus low delayMicroseconds(10); IOHi(scl); // Set bus high delayMicroseconds(10); } // Generate a start then stop condition IOLo(sda); // Set bus data low delayMicroseconds(10); IOLo(scl); // Set bus scl low delayMicroseconds(10); IOHi(scl); // Set bus scl high delayMicroseconds(10); IOHi(sda); // Set bus sda high }
void serialInputPortConfig(ioTag_t pin, uint8_t portIndex) { IOInit(IOGetByTag(pin), OWNER_SOFTSERIAL, RESOURCE_UART_RX, RESOURCE_INDEX(portIndex)); #ifdef STM32F1 IOConfigGPIO(IOGetByTag(pin), IOCFG_IPU); #else IOConfigGPIO(IOGetByTag(pin), IOCFG_AF_PP_UP); #endif }
void i2cInit(I2CDevice device) { UNUSED(device); scl = IOGetByTag(IO_TAG(SOFT_I2C_SCL)); sda = IOGetByTag(IO_TAG(SOFT_I2C_SDA)); IOConfigGPIO(scl, IOCFG_OUT_OD); IOConfigGPIO(sda, IOCFG_OUT_OD); }
static void serialOutputPortDeActivate(softSerial_t *softSerial) { #ifdef STM32F7 if (softSerial->exTimerHardware) IOConfigGPIOAF(softSerial->txIO, IOCFG_IN_FLOATING, softSerial->exTimerHardware->alternateFunction); else IOConfigGPIO(softSerial->txIO, IOCFG_IN_FLOATING); #else IOConfigGPIO(softSerial->txIO, IOCFG_IN_FLOATING); #endif }
// USART2 - GPS or Spektrum or ?? (RX + TX by IRQ) uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t options) { uartPort_t *s; static volatile uint8_t rx2Buffer[UART2_RX_BUFFER_SIZE]; static volatile uint8_t tx2Buffer[UART2_TX_BUFFER_SIZE]; NVIC_InitTypeDef NVIC_InitStructure; s = &uartPort2; s->port.vTable = uartVTable; s->port.baudRate = baudRate; s->port.rxBufferSize = UART2_RX_BUFFER_SIZE; s->port.txBufferSize = UART2_TX_BUFFER_SIZE; s->port.rxBuffer = rx2Buffer; s->port.txBuffer = tx2Buffer; s->USARTx = USART2; s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; RCC_ClockCmd(RCC_APB1(USART2), ENABLE); // UART2_TX PA2 // UART2_RX PA3 if (options & SERIAL_BIDIR) { IOInit(IOGetByTag(IO_TAG(PA2)), OWNER_SERIAL_TX, 2); IOConfigGPIO(IOGetByTag(IO_TAG(PA2)), IOCFG_AF_OD); } else { if (mode & MODE_TX) { IOInit(IOGetByTag(IO_TAG(PA2)), OWNER_SERIAL_TX, 2); IOConfigGPIO(IOGetByTag(IO_TAG(PA2)), IOCFG_AF_PP); } if (mode & MODE_RX) { IOInit(IOGetByTag(IO_TAG(PA3)), OWNER_SERIAL_RX, 2); IOConfigGPIO(IOGetByTag(IO_TAG(PA3)), IOCFG_IPU); } } // RX/TX Interrupt NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART2); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART2); NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); return s; }
void servoInit(const servoConfig_t *servoConfig) { for (uint8_t servoIndex = 0; servoIndex < MAX_SUPPORTED_SERVOS; servoIndex++) { const ioTag_t tag = servoConfig->ioTags[servoIndex]; if (!tag) { break; } servos[servoIndex].io = IOGetByTag(tag); IOInit(servos[servoIndex].io, OWNER_SERVO, RESOURCE_INDEX(servoIndex)); IOConfigGPIO(servos[servoIndex].io, IOCFG_AF_PP); const timerHardware_t *timer = timerGetByTag(tag, TIM_USE_ANY); if (timer == NULL) { /* flag failure and disable ability to arm */ break; } pwmOutConfig(&servos[servoIndex], timer, PWM_TIMER_MHZ, 1000000 / servoConfig->servoPwmRate, servoConfig->servoCenterPulse); servos[servoIndex].enabled = true; } }
void max7456Init(const vcdProfile_t *pVcdProfile) { #ifdef MAX7456_SPI_CS_PIN max7456CsPin = IOGetByTag(IO_TAG(MAX7456_SPI_CS_PIN)); #endif IOInit(max7456CsPin, OWNER_OSD_CS, 0); IOConfigGPIO(max7456CsPin, SPI_IO_CS_CFG); spiSetDivisor(MAX7456_SPI_INSTANCE, SPI_CLOCK_STANDARD); // force soft reset on Max7456 ENABLE_MAX7456; max7456Send(MAX7456ADD_VM0, MAX7456_RESET); DISABLE_MAX7456; // Setup values to write to registers videoSignalCfg = pVcdProfile->video_system; hosRegValue = 32 - pVcdProfile->h_offset; vosRegValue = 16 - pVcdProfile->v_offset; #ifdef MAX7456_DMA_CHANNEL_TX dmaSetHandler(MAX7456_DMA_IRQ_HANDLER_ID, max7456_dma_irq_handler, NVIC_PRIO_MAX7456_DMA, 0); #endif // Real init will be made later when driver detect idle. }
void mpuIntExtiInit(void) { static bool mpuExtiInitDone = false; if (mpuExtiInitDone || !mpuIntExtiConfig) { return; } #if defined(USE_MPU_DATA_READY_SIGNAL) && defined(USE_EXTI) IO_t mpuIntIO = IOGetByTag(mpuIntExtiConfig->tag); #ifdef ENSURE_MPU_DATA_READY_IS_LOW uint8_t status = IORead(mpuIntIO); if (status) { return; } #endif IOInit(mpuIntIO, OWNER_MPU, RESOURCE_EXTI, 0); IOConfigGPIO(mpuIntIO, IOCFG_IN_FLOATING); // TODO - maybe pullup / pulldown ? EXTIHandlerInit(&mpuIntCallbackRec, mpuIntExtiHandler); EXTIConfig(mpuIntIO, &mpuIntCallbackRec, NVIC_PRIO_MPU_INT_EXTI, EXTI_Trigger_Rising); EXTIEnable(mpuIntIO, true); #endif mpuExtiInitDone = true; }
/** * Initialize the driver, must be called before any other routines. * * Attempts to detect a connected m25p16. If found, true is returned and device capacity can be fetched with * m25p16_getGeometry(). */ bool m25p16_init(ioTag_t csTag) { /* if we have already detected a flash device we can simply exit TODO: change the init param in favour of flash CFG when ParamGroups work is done then cs pin can be specified in hardware_revision.c or config.c (dependent on revision). */ if (geometry.sectors) { return true; } if (csTag) { m25p16CsPin = IOGetByTag(csTag); } else { #ifdef M25P16_CS_PIN m25p16CsPin = IOGetByTag(IO_TAG(M25P16_CS_PIN)); #else return false; #endif } IOInit(m25p16CsPin, OWNER_FLASH_CS, 0); IOConfigGPIO(m25p16CsPin, SPI_IO_CS_CFG); DISABLE_M25P16; #ifndef M25P16_SPI_SHARED //Maximum speed for standard READ command is 20mHz, other commands tolerate 25mHz spiSetDivisor(M25P16_SPI_INSTANCE, SPI_CLOCK_FAST); #endif return m25p16_readIdentification(); }
void ledInit(bool alternative_led) { uint32_t i; #if defined(LED0_A) || defined(LED1_A) || defined(LED2_A) if (alternative_led) ledOffset = LED_NUMBER; #else UNUSED(alternative_led); #endif LED0_OFF; LED1_OFF; LED2_OFF; for (i = 0; i < LED_NUMBER; i++) { if (leds[i + ledOffset]) { IOInit(leds[i + ledOffset], OWNER_LED, RESOURCE_OUTPUT, RESOURCE_INDEX(i)); IOConfigGPIO(leds[i + ledOffset], IOCFG_OUT_PP); } } LED0_OFF; LED1_OFF; LED2_OFF; }
static void hmc5883lConfigureDataReadyInterruptHandling(magDev_t* mag) { #ifdef USE_MAG_DATA_READY_SIGNAL if (mag->magIntExtiTag == IO_TAG_NONE) { return; } const IO_t magIntIO = IOGetByTag(mag->magIntExtiTag); #ifdef ENSURE_MAG_DATA_READY_IS_HIGH uint8_t status = IORead(magIntIO); if (!status) { return; } #endif #if defined (STM32F7) IOInit(magIntIO, OWNER_COMPASS_EXTI, 0); EXTIHandlerInit(&mag->exti, hmc5883_extiHandler); EXTIConfig(magIntIO, &mag->exti, NVIC_PRIO_MPU_INT_EXTI, IO_CONFIG(GPIO_MODE_INPUT,0,GPIO_NOPULL)); EXTIEnable(magIntIO, true); #else IOInit(magIntIO, OWNER_COMPASS_EXTI, 0); IOConfigGPIO(magIntIO, IOCFG_IN_FLOATING); EXTIHandlerInit(&mag->exti, hmc5883_extiHandler); EXTIConfig(magIntIO, &mag->exti, NVIC_PRIO_MAG_INT_EXTI, EXTI_Trigger_Rising); EXTIEnable(magIntIO, true); #endif #else UNUSED(mag); #endif }
void adcHardwareInit(drv_adc_config_t *init) { UNUSED(init); int configuredAdcChannels = 0; for (int i = ADC_CHN_1; i < ADC_CHN_COUNT; i++) { if (!adcConfig[i].tag) continue; adcDevice_t * adc = &adcHardware[adcConfig[i].adcDevice]; IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC, RESOURCE_ADC_CH1 + (i - ADC_CHN_1), 0); IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL)); adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag); adcConfig[i].dmaIndex = adc->usedChannelCount++; adcConfig[i].sampleTime = ADC_SampleTime_601Cycles5; adcConfig[i].enabled = true; adc->enabled = true; configuredAdcChannels++; } if (configuredAdcChannels == 0) return; RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div256); // 72 MHz divided by 256 = 281.25 kHz for (int i = 0; i < ADCDEV_COUNT; i++) { if (adcHardware[i].enabled) { adcInstanceInit(i); } } }
static pwmOutputPort_t *pwmOutConfig(const timerHardware_t *timerHardware, uint8_t mhz, uint16_t period, uint16_t value, bool enableOutput) { pwmOutputPort_t *p = &pwmOutputPorts[allocatedOutputPortCount++]; configTimeBase(timerHardware->tim, period, mhz); const IO_t io = IOGetByTag(timerHardware->tag); IOInit(io, OWNER_MOTOR, RESOURCE_OUTPUT, allocatedOutputPortCount); if (enableOutput) { // If PWM outputs are enabled - configure as AF_PP - map to timer // AF itself was configured by timerInit(); IOConfigGPIO(io, IOCFG_AF_PP); } else { // If PWM outputs are disabled - configure as GPIO and drive low IOConfigGPIO(io, IOCFG_OUT_OD); IOLo(io); } pwmOCConfig(timerHardware->tim, timerHardware->channel, value, timerHardware->output & TIMER_OUTPUT_INVERTED); if (timerHardware->output & TIMER_OUTPUT_ENABLED) { TIM_CtrlPWMOutputs(timerHardware->tim, ENABLE); } TIM_Cmd(timerHardware->tim, ENABLE); switch (timerHardware->channel) { case TIM_Channel_1: p->ccr = &timerHardware->tim->CCR1; break; case TIM_Channel_2: p->ccr = &timerHardware->tim->CCR2; break; case TIM_Channel_3: p->ccr = &timerHardware->tim->CCR3; break; case TIM_Channel_4: p->ccr = &timerHardware->tim->CCR4; break; } p->period = period; p->tim = timerHardware->tim; *p->ccr = 0; return p; }
void sdcardInsertionDetectInit(void) { #ifdef SDCARD_DETECT_PIN sdCardDetectPin = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN)); IOInit(sdCardDetectPin, OWNER_SDCARD, RESOURCE_INPUT, 0); IOConfigGPIO(sdCardDetectPin, IOCFG_IPU); #endif }
void usbCableDetectDeinit(void) { #ifdef USB_DETECT_PIN IOInit(usbDetectPin, OWNER_FREE, 0); IOConfigGPIO(usbDetectPin, IOCFG_IN_FLOATING); usbDetectPin = IO_NONE; #endif }
static void NRF24L01_InitGpio(void) { // CE as OUTPUT const SPIDevice rxSPIDevice = spiDeviceByInstance(RX_SPI_INSTANCE); IOInit(DEFIO_IO(RX_CE_PIN), OWNER_RX_SPI_CS, rxSPIDevice + 1); IOConfigGPIO(DEFIO_IO(RX_CE_PIN), SPI_IO_CS_CFG); NRF24_CE_LO(); }
static void initInverter(ioTag_t ioTag) { IO_t pin = IOGetByTag(ioTag); IOInit(pin, OWNER_INVERTER, RESOURCE_OUTPUT, 0); IOConfigGPIO(pin, IOCFG_OUT_PP); inverterSet(pin, false); }
void sdcardInsertionDetectDeinit(void) { #ifdef SDCARD_DETECT_PIN sdCardDetectPin = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN)); IOInit(sdCardDetectPin, OWNER_FREE, RESOURCE_NONE, 0); IOConfigGPIO(sdCardDetectPin, IOCFG_IN_FLOATING); #endif }
static void hmc5883SpiInit(busDevice_t *busdev) { IOHi(busdev->busdev_u.spi.csnPin); // Disable IOInit(busdev->busdev_u.spi.csnPin, OWNER_COMPASS_CS, 0); IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_OUT_PP); spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_STANDARD); }
void usbCableDetectInit(void) { #ifdef USB_DETECT_PIN usbDetectPin = IOGetByTag(IO_TAG(USB_DETECT_PIN)); IOInit(usbDetectPin, OWNER_USB_DETECT, 0); IOConfigGPIO(usbDetectPin, IOCFG_OUT_PP); #endif }
void detectHardwareRevision(void) { IO_t pin1 = IOGetByTag(IO_TAG(PB12)); IOInit(pin1, OWNER_SYSTEM, RESOURCE_INPUT, 1); IOConfigGPIO(pin1, IOCFG_IPU); IO_t pin2 = IOGetByTag(IO_TAG(PB13)); IOInit(pin2, OWNER_SYSTEM, RESOURCE_INPUT, 2); IOConfigGPIO(pin2, IOCFG_IPU); // Check hardware revision delayMicroseconds(10); // allow configuration to settle /* if both PB12 and 13 are tied to GND then it is Rev3A (mini) if only PB12 is tied to GND then it is a Rev3 (full size) */ if (!IORead(pin1)) { if (!IORead(pin2)) { hardwareRevision = BJF4_REV3A; } hardwareRevision = BJF4_REV3; } if (hardwareRevision == UNKNOWN) { hardwareRevision = BJF4_REV2; return; } /* enable the UART1 inversion PC9 TODO: once param groups are in place, inverter outputs can be moved to be simple IO outputs, and merely set them HI or LO in configuration. */ IO_t uart1invert = IOGetByTag(IO_TAG(PC9)); IOInit(uart1invert, OWNER_INVERTER, RESOURCE_OUTPUT, 2); IOConfigGPIO(uart1invert, IOCFG_AF_PP); IOLo(uart1invert); }
void beeperInit(const beeperDevConfig_t *config) { #if !defined(BEEPER) UNUSED(config); #else beeperIO = IOGetByTag(config->ioTag); beeperInverted = config->isInverted; if (beeperIO) { IOInit(beeperIO, OWNER_BEEPER, RESOURCE_OUTPUT, 0); #if defined(BEEPER_PWM) configBeeperPWMTimer(config); IOConfigGPIO(beeperIO, config->isOD ? IOCFG_AF_OD : IOCFG_AF_PP); #else IOConfigGPIO(beeperIO, config->isOD ? IOCFG_OUT_OD : IOCFG_OUT_PP); #endif } systemBeep(false); #endif }
void usbGenerateDisconnectPulse(void) { /* Pull down PA12 to create USB disconnect pulse */ IO_t usbPin = IOGetByTag(IO_TAG(PA12)); IOConfigGPIO(usbPin, IOCFG_OUT_OD); IOLo(usbPin); delay(200); IOHi(usbPin); }
static inline void mma8451ConfigureInterrupt(void) { #ifdef MMA8451_INT_PIN IOInit(IOGetByTag(IO_TAG(MMA8451_INT_PIN)), OWNER_MPU_EXTI, 0); // TODO - maybe pullup / pulldown ? IOConfigGPIO(IOGetByTag(IO_TAG(MMA8451_INT_PIN)), IOCFG_IN_FLOATING); #endif i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG3, MMA8452_CTRL_REG3_IPOL); // Interrupt polarity (active HIGH) i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG4, MMA8452_CTRL_REG4_INT_EN_DRDY); // Enable DRDY interrupt (unused by this driver) i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG5, 0); // DRDY routed to INT2 }
void targetPreInit(void) { switch (hardwareRevision) { case BJF4_REV3: case BJF4_MINI_REV3A: case BJF4_REV4: break; default: return; } IO_t inverter = IOGetByTag(IO_TAG(UART1_INVERTER)); IOInit(inverter, OWNER_INVERTER, 1); IOConfigGPIO(inverter, IOCFG_OUT_PP); bool high = false; serialPortConfig_t *portConfig = serialFindPortConfiguration(SERIAL_PORT_USART1); if (portConfig) { bool smartportEnabled = (portConfig->functionMask & FUNCTION_TELEMETRY_SMARTPORT); if (smartportEnabled && (telemetryConfig()->telemetry_inversion) && (feature(FEATURE_TELEMETRY))) { high = true; } } /* reverse this for rev4, as it does not use the XOR gate */ if (hardwareRevision == BJF4_REV4) { high = !high; } IOWrite(inverter, high); /* ensure the CS pin for the flash is pulled hi so any SD card initialisation does not impact the chip */ if (hardwareRevision == BJF4_REV3) { IO_t flashIo = IOGetByTag(IO_TAG(M25P16_CS_PIN)); IOConfigGPIO(flashIo, IOCFG_OUT_PP); IOHi(flashIo); IO_t sdcardIo = IOGetByTag(IO_TAG(SDCARD_SPI_CS_PIN)); IOConfigGPIO(sdcardIo, IOCFG_OUT_PP); IOHi(sdcardIo); } }
static void i2cUnstick(IO_t scl, IO_t sda) { int i; IOHi(scl); IOHi(sda); IOConfigGPIO(scl, IOCFG_OUT_OD); IOConfigGPIO(sda, IOCFG_OUT_OD); // Clock out, with SDA high: // 7 data bits // 1 READ bit // 1 cycle for the ACK for (i = 0; i < (LEN_ADDR + LEN_RW + LEN_ACK); i++) { // Wait for any clock stretching to finish int timeout = UNSTICK_CLK_STRETCH; while (!IORead(scl) && timeout) { delayMicroseconds(UNSTICK_CLK_US); timeout--; } // Pull low IOLo(scl); // Set bus low delayMicroseconds(UNSTICK_CLK_US/2); IOHi(scl); // Set bus high delayMicroseconds(UNSTICK_CLK_US/2); } // Generate a stop condition in case there was none IOLo(scl); delayMicroseconds(UNSTICK_CLK_US/2); IOLo(sda); delayMicroseconds(UNSTICK_CLK_US/2); IOHi(scl); // Set bus scl high delayMicroseconds(UNSTICK_CLK_US/2); IOHi(sda); // Set bus sda high }
static void serialInputPortDeActivate(softSerial_t *softSerial) { // Disable input capture #ifdef USE_HAL_DRIVER TIM_CCxChannelCmd(softSerial->timerHardware->tim, softSerial->timerHardware->channel, TIM_CCx_DISABLE); #else TIM_CCxCmd(softSerial->timerHardware->tim, softSerial->timerHardware->channel, TIM_CCx_Disable); #endif IOConfigGPIO(softSerial->rxIO, IOCFG_IN_FLOATING); softSerial->rxActive = false; }
bool mpu6000SpiDetect(void) { uint8_t in; uint8_t attemptsRemaining = 5; #ifdef MPU6000_CS_PIN mpuSpi6000CsPin = IOGetByTag(IO_TAG(MPU6000_CS_PIN)); #endif IOInit(mpuSpi6000CsPin, OWNER_MPU, RESOURCE_SPI_CS, 0); IOConfigGPIO(mpuSpi6000CsPin, SPI_IO_CS_CFG); spiSetDivisor(MPU6000_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); mpu6000WriteRegister(MPU_RA_PWR_MGMT_1, BIT_H_RESET); do { delay(150); mpu6000ReadRegister(MPU_RA_WHO_AM_I, 1, &in); if (in == MPU6000_WHO_AM_I_CONST) { break; } if (!attemptsRemaining) { return false; } } while (attemptsRemaining--); mpu6000ReadRegister(MPU_RA_PRODUCT_ID, 1, &in); /* look for a product ID we recognise */ // verify product revision switch (in) { case MPU6000ES_REV_C4: case MPU6000ES_REV_C5: case MPU6000_REV_C4: case MPU6000_REV_C5: case MPU6000ES_REV_D6: case MPU6000ES_REV_D7: case MPU6000ES_REV_D8: case MPU6000_REV_D6: case MPU6000_REV_D7: case MPU6000_REV_D8: case MPU6000_REV_D9: case MPU6000_REV_D10: return true; } return false; }