Ejemplo n.º 1
0
int
I2C::transfer(i2c_msg_s *msgv, unsigned msgs)
{
	int ret;
	unsigned retry_count = 0;

	/* force the device address into the message vector */
	for (unsigned i = 0; i < msgs; i++)
		msgv[i].addr = _address;


	do {
		/*
		 * I2C architecture means there is an unavoidable race here
		 * if there are any devices on the bus with a different frequency
		 * preference.  Really, this is pointless.
		 */
		I2C_SETFREQUENCY(_dev, _frequency);
		ret = I2C_TRANSFER(_dev, msgv, msgs);

		/* success */
		if (ret == OK)
			break;

		/* if we have already retried once, or we are going to give up, then reset the bus */
		if ((retry_count >= 1) || (retry_count >= _retries))
			up_i2creset(_dev);

	} while (retry_count++ < _retries);

	return ret;
}
Ejemplo n.º 2
0
static void
at24xxx_attach(void)
{
	/* find the right I2C */
	struct i2c_dev_s *i2c = up_i2cinitialize(PX4_I2C_BUS_ONBOARD);
	/* this resets the I2C bus, set correct bus speed again */
	I2C_SETFREQUENCY(i2c, 400000);

	if (i2c == NULL)
		errx(1, "failed to locate I2C bus");

	/* start the MTD driver, attempt 5 times */
	for (int i = 0; i < 5; i++) {
		mtd_dev = at24c_initialize(i2c);
		if (mtd_dev) {
			/* abort on first valid result */
			if (i > 0) {
				warnx("warning: EEPROM needed %d attempts to attach", i+1);
			}
			break;
		}
	}

	/* if last attempt is still unsuccessful, abort */
	if (mtd_dev == NULL)
		errx(1, "failed to initialize EEPROM driver");

	attached = true;
}
Ejemplo n.º 3
0
Archivo: kxtj9.c Proyecto: jksim/nuttx
int kxtj9_driver_init(){
    int ret = 0;

    if (g_data != NULL)
        goto init_done;
    g_data = kmm_malloc(sizeof(struct kxtj9_data));
    memset(g_data, 0, sizeof(struct kxtj9_data));

    g_data->i2c = up_i2cinitialize(CONFIG_SENSOR_KXTJ9_I2C_BUS);
    if (!g_data->i2c) {
        dbg("failed to init i2c\n");
        ret = -ENODEV;
        goto init_done;
    }

    ret = I2C_SETADDRESS(g_data->i2c, KXTJ9_I2C_ADDR, 7);
    if (ret) {
        dbg("failed to set i2c address\n");
        goto init_done;
    }

    I2C_SETFREQUENCY(g_data->i2c, CONFIG_SENSOR_KXTJ9_I2C_BUS_SPEED);

init_done:
    return ret;
}
Ejemplo n.º 4
0
FAR struct battery_charger_dev_s *bq2425x_initialize(FAR struct i2c_dev_s *i2c,
                            uint8_t addr, uint32_t frequency)
{
  FAR struct bq2425x_dev_s *priv;
  int ret;

  /* Initialize the BQ2425x device structure */

  priv = (FAR struct bq2425x_dev_s *)kmm_zalloc(sizeof(struct bq2425x_dev_s));
  if (priv)
    {
      /* Initialize the BQ2425x device structure */

      sem_init(&priv->batsem, 0, 1);
      priv->ops       = &g_bq2425xops;
      priv->i2c       = i2c;
      priv->addr      = addr;
      priv->frequency = frequency;

      /* Set the I2C frequency (ignoring the returned, actual frequency) */

      (void)I2C_SETFREQUENCY(i2c, priv->frequency);

      /* Reset the BQ2425x */

      ret = bq2425x_reset(priv);
      if (ret < 0)
        {
          batdbg("Failed to reset the BQ2425x: %d\n", ret);
          kmm_free(priv);
          return NULL;
        }

      /* Disable watchdog otherwise BQ2425x returns to StandAlone mode */

      ret = bq2425x_watchdog(priv, false);
      if (ret < 0)
        {
          batdbg("Failed to disable BQ2425x watchdog: %d\n", ret);
          kmm_free(priv);
          return NULL;
        }

      /* Define that our power supply can offer 2000mA to the charger */

      ret = bq2425x_powersupply(priv, 2000);
      if (ret < 0)
        {
          batdbg("Failed to set BQ2425x power supply current: %d\n", ret);
          kmm_free(priv);
          return NULL;
        }
    }

  return (FAR struct battery_charger_dev_s *)priv;
}
Ejemplo n.º 5
0
int
I2C::transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len)
{
	struct i2c_msg_s msgv[2];
	unsigned msgs;
	int ret;
	unsigned retry_count = 0;

	do {
		//	debug("transfer out %p/%u  in %p/%u", send, send_len, recv, recv_len);

		msgs = 0;

		if (send_len > 0) {
			msgv[msgs].addr = _address;
			msgv[msgs].flags = 0;
			msgv[msgs].buffer = const_cast<uint8_t *>(send);
			msgv[msgs].length = send_len;
			msgs++;
		}

		if (recv_len > 0) {
			msgv[msgs].addr = _address;
			msgv[msgs].flags = I2C_M_READ;
			msgv[msgs].buffer = recv;
			msgv[msgs].length = recv_len;
			msgs++;
		}

		if (msgs == 0)
			return -EINVAL;

		/*
		 * I2C architecture means there is an unavoidable race here
		 * if there are any devices on the bus with a different frequency
		 * preference.  Really, this is pointless.
		 */
		I2C_SETFREQUENCY(_dev, _frequency);
		ret = I2C_TRANSFER(_dev, &msgv[0], msgs);

		/* success */
		if (ret == OK)
			break;

		/* if we have already retried once, or we are going to give up, then reset the bus */
		if ((retry_count >= 1) || (retry_count >= _retries))
			up_i2creset(_dev);

	} while (retry_count++ < _retries);

	return ret;

}
Ejemplo n.º 6
0
int i2c_writeread(FAR struct i2c_dev_s *dev, FAR const struct i2c_config_s *config, FAR const uint8_t *wbuffer, int wbuflen, FAR uint8_t *rbuffer, int rbuflen)
{
	struct i2c_msg_s msg[2];
	unsigned int flags;
	int ret = -1;

	/* 7- or 10-bit address? */

	DEBUGASSERT(config->addrlen == 10 || config->addrlen == 7);
	flags = (config->addrlen == 10) ? I2C_M_TEN : 0;

	/* Format two messages: The first is a write */

	msg[0].addr = config->address;
	msg[0].flags = flags;
	msg[0].buffer = (FAR uint8_t *)wbuffer;	/* Override const */
	msg[0].length = wbuflen;

	/* The second is either a read (rbuflen > 0) or a write (rbuflen < 0) with
	 * no restart.
	 */

	if (rbuflen > 0) {
		msg[1].flags = (flags | I2C_M_READ);
	} else {
		msg[1].flags = (flags | I2C_M_NORESTART);
		rbuflen = -rbuflen;
	}

	msg[1].addr = config->address;
	msg[1].buffer = rbuffer;
	msg[1].length = rbuflen;

	/* Then perform the transfer
	 *
	 * REVISIT:  The following two operations must become atomic in order to
	 * assure thread safety.
	 */

	if (dev != 0x0) {
		I2C_SETFREQUENCY(dev, config->frequency);
		ret = I2C_TRANSFER(dev, msg, 2);
	}

	return ret;
}
Ejemplo n.º 7
0
static int
transfer(uint8_t address, uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len)
{
	struct i2c_msg_s msgv[2];
	unsigned msgs;
	int ret;

	//	debug("transfer out %p/%u  in %p/%u", send, send_len, recv, recv_len);

	msgs = 0;

	if (send_len > 0) {
		msgv[msgs].addr = address;
		msgv[msgs].flags = 0;
		msgv[msgs].buffer = send;
		msgv[msgs].length = send_len;
		msgs++;
	}

	if (recv_len > 0) {
		msgv[msgs].addr = address;
		msgv[msgs].flags = I2C_M_READ;
		msgv[msgs].buffer = recv;
		msgv[msgs].length = recv_len;
		msgs++;
	}

	if (msgs == 0)
		return -1;

	/*
	 * I2C architecture means there is an unavoidable race here
	 * if there are any devices on the bus with a different frequency
	 * preference.  Really, this is pointless.
	 */
	I2C_SETFREQUENCY(i2c, 400000);
	ret = I2C_TRANSFER(i2c, &msgv[0], msgs);

	// reset the I2C bus to unwedge on error
	if (ret != OK)
		up_i2creset(i2c);

	return ret;
}
Ejemplo n.º 8
0
FAR struct battery_dev_s *max1704x_initialize(FAR struct i2c_dev_s *i2c,
                            uint8_t addr, uint32_t frequency)
{
  FAR struct max1704x_dev_s *priv;
#if 0
  int ret;
#endif

  /* Initialize the MAX1704x device structure */

  priv = (FAR struct max1704x_dev_s *)kzalloc(sizeof(struct max1704x_dev_s));
  if (priv)
    {
      /* Initialize the MAX1704x device structure */

      sem_init(&priv->batsem, 0, 1);
      priv->ops       = &g_max1704xops;
      priv->i2c       = i2c;
      priv->addr      = addr;
      priv->frequency = frequency;

      /* Set the I2C frequency (ignoring the returned, actual frequency) */

      (void)I2C_SETFREQUENCY(i2c, priv->frequency);

      /* Reset the MAX1704x (mostly just to make sure that we can talk to it) */

#if 0
      ret = max1704x_reset(priv);
      if (ret < 0)
        {
          batdbg("Failed to reset the MAX1704x: %d\n", ret);
          kfree(priv);
          return NULL;
        }
#endif
    }
  return (FAR struct battery_dev_s *)priv;
}
Ejemplo n.º 9
0
int pca9635pw_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c,
                       uint8_t const pca9635pw_i2c_addr)
{
  /* Sanity check */

  DEBUGASSERT(i2c != NULL);

  /* Initialize the PCA9635PW device structure */

  FAR struct pca9635pw_dev_s *priv =
    (FAR struct pca9635pw_dev_s *)kmm_malloc(sizeof(struct pca9635pw_dev_s));

  if (priv == NULL)
    {
      dbg("Failed to allocate instance of pca9635pw_dev_s\n");
      return -ENOMEM;
    }

  priv->i2c = i2c;
  priv->i2c_addr = pca9635pw_i2c_addr;

  /* Register the character driver */

  int const ret = register_driver(devpath, &g_pca9635pw_fileops, 666, priv);
  if (ret != OK)
    {
      dbg("Failed to register driver: %d\n", ret);
      kmm_free(priv);
      return ret;
    }

  /* setup i2c frequency */

  I2C_SETFREQUENCY(priv->i2c, I2C_BUS_FREQ_HZ);

  return OK;
}
Ejemplo n.º 10
0
STMPE811_HANDLE stmpe811_instantiate(FAR struct i2c_dev_s *dev,
                                     FAR struct stmpe811_config_s *config)
#endif
{
  FAR struct stmpe811_dev_s *priv;
  uint8_t regval;
  int ret;

  /* Allocate the device state structure */

#ifdef CONFIG_STMPE811_MULTIPLE
  priv = (FAR struct stmpe811_dev_s *)kmm_zalloc(sizeof(struct stmpe811_dev_s));
  if (!priv)
    {
      return NULL;
    }

  /* And save the device structure in the list of STMPE811 so that we can find it later */

  priv->flink   = g_stmpe811list;
  g_stmpe811list = priv;
#else

  /* Use the one-and-only STMPE811 driver instance */

  priv = &g_stmpe811;
#endif

  /* Initialize the device state structure */

  sem_init(&priv->exclsem, 0, 1);
  priv->config = config;

#ifdef CONFIG_STMPE811_SPI
  priv->spi = dev;
#else
  priv->i2c = dev;

  /* Set the I2C address and frequency.  REVISIT:  This logic would be
   * insufficient if we share the I2C bus with any other devices that also
   * modify the address and frequency.
   */

  I2C_SETADDRESS(dev, config->address, 7);
  I2C_SETFREQUENCY(dev, config->frequency);
#endif

  /* Read and verify the STMPE811 chip ID */

  ret = stmpe811_checkid(priv);
  if (ret < 0)
    {
#ifdef CONFIG_STMPE811_MULTIPLE
      g_stmpe811list = priv->flink;
      kmm_free(priv);
#endif
      return NULL;
    }

  /* Generate STMPE811 Software reset */

  stmpe811_reset(priv);

  /* Configure the interrupt output pin to generate interrupts on high or low level. */

  regval  = stmpe811_getreg8(priv, STMPE811_INT_CTRL);
#ifdef CONFIG_STMPE811_ACTIVELOW
  regval &= ~INT_CTRL_INT_POLARITY; /* Pin polarity: Active low / falling edge */
#else
  regval |= INT_CTRL_INT_POLARITY;  /* Pin polarity: Active high / rising edge */
#endif
#ifdef CONFIG_STMPE811_EDGE
  regval |= INT_CTRL_INT_TYPE;      /* Edge interrupt */
#else
  regval &= ~INT_CTRL_INT_TYPE;     /* Level interrupt */
#endif
  stmpe811_putreg8(priv, STMPE811_INT_CTRL, regval);

  /* Attach the STMPE811 interrupt handler. */

  config->attach(config, stmpe811_interrupt);

  /* Clear any pending interrupts */

  stmpe811_putreg8(priv, STMPE811_INT_STA, INT_ALL);
  config->clear(config);
  config->enable(config, true);

  /* Enable global interrupts */

  regval  = stmpe811_getreg8(priv, STMPE811_INT_CTRL);
  regval |= INT_CTRL_GLOBAL_INT;
  stmpe811_putreg8(priv, STMPE811_INT_CTRL, regval);

  /* Return our private data structure as an opaque handle */

  return (STMPE811_HANDLE)priv;
}
Ejemplo n.º 11
0
int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
{
  FAR struct i2c_dev_s *dev;
  FAR char *ptr;
  uint16_t result;
  uint8_t regaddr;
  long repititions;
  int nargs;
  int argndx;
  int ret;
  int i;

  /* Parse any command line arguments */

  for (argndx = 1; argndx < argc; )
    {
      /* Break out of the look when the last option has been parsed */

      ptr = argv[argndx];
      if (*ptr != '-')
        {
          break;
        }

      /* Otherwise, check for common options */

      nargs = common_args(i2ctool, &argv[argndx]);
      if (nargs < 0)
        {
          return ERROR;
        }
      argndx += nargs;
    }

  /* There may be one more thing on the command line:  The repitition
   * count.
   */

  repititions = 1;
  if (argndx < argc)
    {
      repititions = strtol(argv[argndx], NULL, 16);
      if (repititions < 1)
        {
          i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
          return ERROR;
        }

      argndx++;
    }

  if (argndx != argc)
    {
      i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]);
      return ERROR;
    }

  /* Get a handle to the I2C bus */

  dev = up_i2cinitialize(i2ctool->bus);
  if (!dev)
    {
       i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus);
       return ERROR;
    }

  /* Set the frequency and the address (NOTE:  Only 7-bit address supported now) */

  I2C_SETFREQUENCY(dev, i2ctool->freq);
  I2C_SETADDRESS(dev, i2ctool->addr, 7);

  /* Loop for the requested number of repititions */

  regaddr = i2ctool->regaddr;
  ret = OK;

  for (i = 0; i < repititions; i++)
    {
      /* Read from the I2C bus */

      ret = i2ctool_get(i2ctool, dev, regaddr, &result);

      /* Display the result */

      if (ret == OK)
        {
          i2ctool_printf(i2ctool, "READ Bus: %d Addr: %02x Subaddr: %02x Value: ",
                         i2ctool->bus, i2ctool->addr, i2ctool->regaddr);
          if (i2ctool->width == 8)
            {
              i2ctool_printf(i2ctool, "%02x\n", result);
            }
          else
            {
              i2ctool_printf(i2ctool, "%04x\n", result);
            }
        }
      else
        {
          i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
          break;
        }

      /* Auto-increment the address if so configured */

      if (i2ctool->autoincr)
        {
          regaddr++;
        }
    }

  (void)up_i2cuninitialize(dev);
  return ret;
}
Ejemplo n.º 12
0
int nsh_archinitialize(void)
{
  int result;

  /* INIT 1 Lowest level NuttX initialization has been done at this point, LEDs and UARTs are configured */

  /* INIT 2 Configuring PX4 low-level peripherals, these will be always needed */

  /* configure the high-resolution time/callout interface */
#ifdef CONFIG_HRT_TIMER
  hrt_init();
#endif

  /* configure CPU load estimation */
  #ifdef CONFIG_SCHED_INSTRUMENTATION
  cpuload_initialize_once();
  #endif

  /* set up the serial DMA polling */
#ifdef SERIAL_HAVE_DMA
  {
    static struct hrt_call serial_dma_call;
    struct timespec ts;

    /* 
     * Poll at 1ms intervals for received bytes that have not triggered
     * a DMA event.
     */
    ts.tv_sec = 0;
    ts.tv_nsec = 1000000;

    hrt_call_every(&serial_dma_call, 
                   ts_to_abstime(&ts),
                   ts_to_abstime(&ts),
                   (hrt_callout)stm32_serial_dma_poll,
                   NULL);
  }
#endif

  message("\r\n");

  up_ledoff(LED_BLUE);
  up_ledoff(LED_AMBER);

  up_ledon(LED_BLUE);

  /* Configure user-space led driver */
  px4fmu_led_init();

  /* Configure SPI-based devices */

  spi1 = up_spiinitialize(1);
  if (!spi1)
  {
	  message("[boot] FAILED to initialize SPI port 1\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  // Setup 10 MHz clock (maximum rate the BMA180 can sustain)
  SPI_SETFREQUENCY(spi1, 10000000);
  SPI_SETBITS(spi1, 8);
  SPI_SETMODE(spi1, SPIDEV_MODE3);
  SPI_SELECT(spi1, PX4_SPIDEV_GYRO, false);
  SPI_SELECT(spi1, PX4_SPIDEV_ACCEL, false);
  SPI_SELECT(spi1, PX4_SPIDEV_MPU, false);
  up_udelay(20);

  message("[boot] Successfully initialized SPI port 1\r\n");

  /* initialize SPI peripherals redundantly */
  int gyro_attempts = 0;
  int gyro_fail = 0;

  while (gyro_attempts < 5)
  {
	  gyro_fail = l3gd20_attach(spi1, PX4_SPIDEV_GYRO);
	  gyro_attempts++;
	  if (gyro_fail == 0) break;
	  up_udelay(1000);
  }

  if (gyro_fail) message("[boot] FAILED to attach L3GD20 gyro\r\n");

  int acc_attempts = 0;
  int acc_fail = 0;

  while (acc_attempts < 5)
  {
	  acc_fail = bma180_attach(spi1, PX4_SPIDEV_ACCEL);
	  acc_attempts++;
	  if (acc_fail == 0) break;
	  up_udelay(1000);
  }

  if (acc_fail) message("[boot] FAILED to attach BMA180 accelerometer\r\n");

  int mpu_attempts = 0;
  int mpu_fail = 0;

  while (mpu_attempts < 1)
  {
	  mpu_fail = mpu6000_attach(spi1, PX4_SPIDEV_MPU);
	  mpu_attempts++;
	  if (mpu_fail == 0) break;
	  up_udelay(200);
  }

  if (mpu_fail) message("[boot] FAILED to attach MPU 6000 gyro/acc\r\n");

  /* initialize I2C2 bus */

  i2c2 = up_i2cinitialize(2);
  if (!i2c2) {
	  message("[boot] FAILED to initialize I2C bus 2\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  /* set I2C2 speed */
  I2C_SETFREQUENCY(i2c2, 400000);


  i2c3 = up_i2cinitialize(3);
  if (!i2c3) {
	  message("[boot] FAILED to initialize I2C bus 3\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  /* set I2C3 speed */
  I2C_SETFREQUENCY(i2c3, 400000);

  int mag_attempts = 0;
  int mag_fail = 0;

  while (mag_attempts < 5)
  {
	  mag_fail = hmc5883l_attach(i2c2);
	  mag_attempts++;
	  if (mag_fail == 0) break;
	  up_udelay(1000);
  }

  if (mag_fail) message("[boot] FAILED to attach HMC5883L magnetometer\r\n");

  int baro_attempts = 0;
  int baro_fail = 0;
  while (baro_attempts < 5)
  {
	  baro_fail = ms5611_attach(i2c2);
	  baro_attempts++;
	  if (baro_fail == 0) break;
	  up_udelay(1000);
  }

  if (baro_fail) message("[boot] FAILED to attach MS5611 baro at addr #1 or #2 (0x76 or 0x77)\r\n");

  /* try to attach, don't fail if device is not responding */
  (void)eeprom_attach(i2c3, FMU_BASEBOARD_EEPROM_ADDRESS,
		  FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/baseboard_eeprom", 1);

  int eeprom_attempts = 0;
  int eeprom_fail;
  while (eeprom_attempts < 5)
  {
	  /* try to attach, fail if device does not respond */
	  eeprom_fail = eeprom_attach(i2c2, FMU_ONBOARD_EEPROM_ADDRESS,
			  FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/eeprom", 1);
	  eeprom_attempts++;
	  if (eeprom_fail == OK) break;
	  up_udelay(1000);
  }

  if (eeprom_fail) message("[boot] FAILED to attach FMU EEPROM\r\n");

  /* Report back sensor status */
  if (acc_fail || gyro_fail || mag_fail || baro_fail || eeprom_fail)
  {
	  up_ledon(LED_AMBER);
  }

#if defined(CONFIG_STM32_SPI3)
  /* Get the SPI port */

  message("[boot] Initializing SPI port 3\r\n");
  spi3 = up_spiinitialize(3);
  if (!spi3)
    {
      message("[boot] FAILED to initialize SPI port 3\r\n");
      up_ledon(LED_AMBER);
      return -ENODEV;
    }
  message("[boot] Successfully initialized SPI port 3\r\n");

  /* Now bind the SPI interface to the MMCSD driver */
  result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3);
  if (result != OK)
  {
	  message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }
  message("[boot] Successfully bound SPI port 3 to the MMCSD driver\r\n");
#endif /* SPI3 */

  /* initialize I2C1 bus */

  i2c1 = up_i2cinitialize(1);
  if (!i2c1) {
    message("[boot] FAILED to initialize I2C bus 1\r\n");
    up_ledon(LED_AMBER);
    return -ENODEV;
  }

  /* set I2C1 speed */
  I2C_SETFREQUENCY(i2c1, 400000);

  /* INIT 3: MULTIPORT-DEPENDENT INITIALIZATION */

  /* Get board information if available */

    /* Initialize the user GPIOs */
  px4fmu_gpio_init();

#ifdef CONFIG_ADC
  int adc_state = adc_devinit();
  if (adc_state != OK)
  {
    /* Try again */
    adc_state = adc_devinit();
    if (adc_state != OK)
    {
      /* Give up */
      message("[boot] FAILED adc_devinit: %d\r\n", adc_state);
      return -ENODEV;
    }
  }
#endif

    /* configure the tone generator */
#ifdef CONFIG_TONE_ALARM
  tone_alarm_init();
#endif

  return OK;
}
Ejemplo n.º 13
0
int i2ccmd_verf(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
{
  FAR struct i2c_dev_s *dev;
  FAR char *ptr;
  uint16_t rdvalue;
  uint8_t regaddr;
  bool addrinaddr;
  long wrvalue;
  long repititions;
  int nargs;
  int argndx;
  int ret;
  int i;

  /* Parse any command line arguments */

  for (argndx = 1; argndx < argc; )
    {
      /* Break out of the look when the last option has been parsed */

      ptr = argv[argndx];
      if (*ptr != '-')
        {
          break;
        }

      /* Otherwise, check for common options */

      nargs = common_args(i2ctool, &argv[argndx]);
      if (nargs < 0)
        {
          return ERROR;
        }
      argndx += nargs;
    }

  /* The options may be followed by the optional wrvalue to be written.  If omitted, then
   * the register address will be used as the wrvalue, providing an address-in-address
   * test.
   */

  addrinaddr = true;
  wrvalue    = 0;

  if (argndx < argc)
    {
      wrvalue = strtol(argv[argndx], NULL, 16);
      if (i2ctool->width == 8)
        {
          if (wrvalue < 0 || wrvalue > 255)
            {
              i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
              return ERROR;
            }
        }
      else if (wrvalue < 0 || wrvalue > 65535)
        {
          i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
          return ERROR;
        }

      addrinaddr = false;
      argndx++;
    }

  /* There may be one more thing on the command line:  The repitition
   * count.
   */

  repititions = 1;
  if (argndx < argc)
    {
      repititions = strtol(argv[argndx], NULL, 16);
      if (repititions < 1)
        {
          i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
          return ERROR;
        }

      argndx++;
    }

  if (argndx != argc)
    {
      i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]);
      return ERROR;
    }

  /* Get a handle to the I2C bus */

  dev = up_i2cinitialize(i2ctool->bus);
  if (!dev)
    {
       i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus);
       return ERROR;
    }

  /* Set the frequency and the address (NOTE:  Only 7-bit address supported now) */

  I2C_SETFREQUENCY(dev, i2ctool->freq);
  I2C_SETADDRESS(dev, i2ctool->addr, 7);

  /* Loop for the requested number of repititions */

  regaddr = i2ctool->regaddr;
  ret = OK;

  for (i = 0; i < repititions; i++)
    {
      /* If we are performing an address-in-address test, then use the register
       * address as the value to write.
       */

      if (addrinaddr)
        {
          wrvalue = regaddr;
        }

      /* Write to the I2C bus */

      ret = i2ctool_set(i2ctool, dev, regaddr, (uint16_t)wrvalue);
      if (ret == OK)
        {
          /* Read the value back from the I2C bus */

          ret = i2ctool_get(i2ctool, dev, regaddr, &rdvalue);
        }

      /* Display the result */

      if (ret == OK)
        {
          i2ctool_printf(i2ctool, "VERIFY Bus: %d Addr: %02x Subaddr: %02x Wrote: ",
                         i2ctool->bus, i2ctool->addr, i2ctool->regaddr);

          if (i2ctool->width == 8)
            {
              i2ctool_printf(i2ctool, "%02x Read: %02x", (int)wrvalue, (int)rdvalue);
            }
          else
            {
              i2ctool_printf(i2ctool, "%04x Read: %04x", (int)wrvalue, (int)rdvalue);
            }

          if (wrvalue != rdvalue)
            {
              i2ctool_printf(i2ctool, "  <<< FAILURE\n");
            }
          else
            {
              i2ctool_printf(i2ctool, "\n");
            }
        }
      else
        {
          i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
          break;
        }

      /* Auto-increment the address if so configured */

      if (i2ctool->autoincr)
        {
          regaddr++;
        }
    }

  (void)up_i2cuninitialize(dev);
  return ret;
}
Ejemplo n.º 14
0
int nsh_archinitialize(void)
{
  int result;

  /* INIT 1 Lowest level NuttX initialization has been done at this point, LEDs and UARTs are configured */

  /* INIT 2 Configuring PX4 low-level peripherals, these will be always needed */

  /* configure the high-resolution time/callout interface */
#ifdef CONFIG_HRT_TIMER
  hrt_init();
#endif

  /* configure CPU load estimation */
  #ifdef CONFIG_SCHED_INSTRUMENTATION
  cpuload_initialize_once();
  #endif

  /* set up the serial DMA polling */
#ifdef SERIAL_HAVE_DMA
  {
    static struct hrt_call serial_dma_call;
    struct timespec ts;

    /* 
     * Poll at 1ms intervals for received bytes that have not triggered
     * a DMA event.
     */
    ts.tv_sec = 0;
    ts.tv_nsec = 1000000;

    hrt_call_every(&serial_dma_call, 
                   ts_to_abstime(&ts),
                   ts_to_abstime(&ts),
                   (hrt_callout)stm32_serial_dma_poll,
                   NULL);
  }
#endif

  message("\r\n");

  up_ledoff(LED_BLUE);
  up_ledoff(LED_AMBER);

  up_ledon(LED_BLUE);

  /* Configure user-space led driver */
  px4fmu_led_init();


  i2c2 = up_i2cinitialize(2);
  if (!i2c2) {
	  message("[boot] FAILED to initialize I2C bus 3\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  /* set I2C3 speed */
  I2C_SETFREQUENCY(i2c2, 400000);

  /* try to attach, don't fail if device is not responding */
  (void)eeprom_attach(i2c2, FMU_BASEBOARD_EEPROM_ADDRESS,
		  FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/baseboard_eeprom", 1);

  int eeprom_attempts = 0;
  int eeprom_fail;
  while (eeprom_attempts < 5)
  {
	  /* try to attach, fail if device does not respond */
	  eeprom_fail = eeprom_attach(i2c2, FMU_ONBOARD_EEPROM_ADDRESS,
			  FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/eeprom", 1);
	  eeprom_attempts++;
	  if (eeprom_fail == OK) break;
	  up_udelay(1000);
  }

  if (eeprom_fail) message("[boot] FAILED to attach FMU EEPROM\r\n");

  /* Report back sensor status */
  if (eeprom_fail)
  {
	  up_ledon(LED_AMBER);
  }

#if defined(CONFIG_STM32_SPI3)
  /* Get the SPI port */

  message("[boot] Initializing SPI port 3\r\n");
  spi3 = up_spiinitialize(3);
  if (!spi3)
    {
      message("[boot] FAILED to initialize SPI port 3\r\n");
      up_ledon(LED_AMBER);
      return -ENODEV;
    }
  message("[boot] Successfully initialized SPI port 3\r\n");

  /* Now bind the SPI interface to the MMCSD driver */
  result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3);
  if (result != OK)
  {
	  message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }
  message("[boot] Successfully bound SPI port 3 to the MMCSD driver\r\n");
#endif /* SPI3 */

  /* INIT 3: MULTIPORT-DEPENDENT INITIALIZATION */

  /* Get board information if available */

    /* Initialize the user GPIOs */
  px4fmu_gpio_init();

#ifdef CONFIG_ADC
  int adc_state = adc_devinit();
  if (adc_state != OK)
  {
    /* Try again */
    adc_state = adc_devinit();
    if (adc_state != OK)
    {
      /* Give up */
      message("[boot] FAILED adc_devinit: %d\r\n", adc_state);
      return -ENODEV;
    }
  }
#endif

    /* configure the tone generator */
#ifdef CONFIG_TONE_ALARM
  tone_alarm_init();
#endif

  return OK;
}
Ejemplo n.º 15
0
int sif_main(int argc, char *argv[])
{
    if (argc >= 2) {	
        if (!strcmp(argv[1], "init")) {
          return sif_init();
        }
        else if (!strcmp(argv[1], "gpio") && argc == 4) {
            vsn_sif.gpio[0] = atoi(argv[2]);
            vsn_sif.gpio[1] = atoi(argv[3]);
            sif_gpio1_update();
            sif_gpio2_update();
            printf("GPIO States: %2x %2x\n", vsn_sif.gpio[0], vsn_sif.gpio[1]);
            return 0;
        }
        else if (!strcmp(argv[1], "pwr") && argc == 3) {
            int val = atoi(argv[2]);
            //STM32_TIM_SETCOMPARE(vsn_sif.tim8, GPIO_OUT_PWRPWM_TIM8_CH, val);
            STM32_TIM_SETCOMPARE(vsn_sif.tim3, GPIO_OUT_PWM_TIM3_CH, val);
            return 0;
        }
        else if (!strcmp(argv[1], "time") && argc == 3) {
            struct timespec t_set;
            t_set.tv_sec = atoi(argv[2]);
            clock_settime(CLOCK_REALTIME, &t_set);
        }
        else if (!strcmp(argv[1], "free")) {
            size_t  page = 0, stpage = 0xFFFF;
            ssize_t status;
            do {
                status = up_progmem_ispageerased(page++);

                /* Is this beginning of new free space section */
                if (status == 0) {
                    if (stpage == 0xFFFF) stpage = page-1;
                }
                else if (status != 0) {
                    if (stpage != 0xFFFF) {
                        printf("Free Range:\t%lu\t-\t%lu\n",
                               (unsigned long)stpage, (unsigned long)(page-2));
                        stpage = 0xFFFF;
                    }
                }
            }
            while (status >= 0);
            return 0;
        }
        else if (!strcmp(argv[1], "erase") && argc == 3) {
            size_t page = atoi(argv[2]);
            printf("Erase result: %d\n", up_progmem_erasepage(page));
            return 0;
        }
        else if (!strcmp(argv[1], "flash") && argc == 3) {
            size_t page = atoi(argv[2]);
            size_t addr = page * up_progmem_pagesize(page);

            printf("Write result: %d (writing to address %lxh)\n",
                up_progmem_write(addr, "Test", 4), (unsigned long)addr);
            return 0;
        }
        else if (!strcmp(argv[1], "i2c") && argc == 3) {
            int val = atoi(argv[2]);

            I2C_SETFREQUENCY(vsn_sif.i2c1, 100000);

            struct lis331dl_dev_s * lis = lis331dl_init(vsn_sif.i2c1, val);

            if (lis) {
                const struct lis331dl_vector_s * a;
                int i;
                uint32_t time_stamp = clock_systimer();

                /* Set to 400 Hz : 3 = 133 Hz/axis */

                lis331dl_setconversion(lis, false, true);

                /* Sample some values */

                for (i=0; i<1000;) {
                    if ((a = lis331dl_getreadings(lis))) {
                        i++;
                        printf("%d %d %d\n", a->x, a->y, a->z);
                    }
                    else if (errno != 11) {
                        printf("Readings errno %d\n", errno);
                        break;
                    }
                }

                printf("Time diff = %d\n", clock_systimer() - time_stamp);

                lis331dl_deinit(lis);
            }
            else printf("Exit point: errno=%d\n", errno);

            return 0;
        }
        else if (!strcmp(argv[1], "pga")) {
            int gain = atoi(argv[2]);

            gain = vsn_muxbus_setpgagain(gain);

            printf("Gain changed: %d\n", gain);
            return 0;
        }
        else if (!strcmp(argv[1], "cc")) {
            struct cc1101_dev_s * cc;
            uint8_t buf[64];
            int sta;

            cc = cc1101_init(vsn_sif.spi2, CC1101_PIN_GDO0, GPIO_CC1101_GDO0,
                &cc1101_rfsettings_ISM1_868MHzGFSK100kbps);

            if (cc) {

                /* Work-around: enable falling edge, event and interrupt */
                stm32_gpiosetevent(GPIO_CC1101_GDO0, false, true, true, cc1101_eventcb);

                /* Enable clock to ARM PLL, allowing to speed-up to 72 MHz */
                cc1101_setgdo(cc, CC1101_PIN_GDO2, CC1101_GDO_CLK_XOSC3);

                cc1101_setchannel(cc, 0);   /* AV Test Hex, receive on that channel */
                cc1101_receive(cc);          /* Enter RX mode */
                while (1)
                {
                    fflush(stdout);
                    sta = cc1101_read(cc, buf, 64);
                    if (sta > 0) {
                        printf("Received %d bytes: rssi=%d [dBm], LQI=%d (CRC %s)\n",
                            sta, cc1101_calcRSSIdBm(buf[sta-2]), buf[sta-1]&0x7F,
                            (buf[sta-1]&0x80)?"OK":"BAD");

                        cc1101_write(cc, buf, 61);
                        cc1101_send(cc);

                        printf("Packet send back\n");

                        cc1101_receive(cc);
                    }
                }
            }
        }
    }

    fprintf(stderr, "%s:\tinit\n\tgpio\tA B\n\tpwr\tval\n", argv[0]);

    fprintf(stderr, "rtc time = %u, time / systick = %u / %u\n",
        up_rtc_time(), time(NULL), clock_systimer());
    return -1;
}
Ejemplo n.º 16
0
int ov2640_initialize(FAR struct i2c_dev_s *i2c)
{
  int ret;

  /* Configure I2C bus for the OV2640 */

  I2C_SETADDRESS(i2c, CONFIG_OV2640_I2CADDR, 7);
  I2C_SETFREQUENCY(i2c, CONFIG_OV2640_FREQUENCY);

  /* Reset the OVR2640 */

  ret = ov2640_reset(i2c);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_reset failed: %d\n", ret);
      goto errout;
    }

  /* Check the CHIP ID */

  ret = ovr2640_chipid(i2c);
  if (ret < 0)
    {
      gdbg("ERROR: ovr2640_chipid failed: %d\n", ret);
      goto errout;
    }

  /* Initialize the OV2640 hardware */

#ifdef CONFIG_OV2640_JPEG
  /* Initialize for JPEG output */

  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_init, OV2640_JPEG_INIT_NENTRIES);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

  ret = ov2640_putreglist(i2c, g_ov2640_yuv422, OV2640_YUV422_NENTRIES);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

  ret = ov2640_putreglist(i2c, g_ov2640_jpeg, OV2640_JPEG_NENTRIES);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

  ret = ov2640_putreg(i2c, 0xff, 0x01);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreg failed: %d\n", ret);
      goto errout;
    }

  ret = ov2640_putreg(i2c, 0x15, 0x00);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreg failed: %d\n", ret);
      goto errout;
    }

#if defined(CONFIG_OV2640_JPEG_QCIF_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_qcif_resolution,
                          OV2640_JPEG_QCIF_RESOUTION_NENTRIES);

#elif defined(CONFIG_OV2640_JPEG_QVGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_qvga_resolution,
                          OV2640_JPEG_QVGA_RESOUTION_NENTRIES);

#elif defined(CONFIG_OV2640_JPEG_CIF_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_cif_resolution,
                          OV2640_JPEG_CIF_RESOUTION_NENTRIES);

#elif defined(CONFIG_OV2640_JPEG_VGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_vga_resolution,
                          OV2640_JPEG_VGA_RESOUTION_NENTRIES);

#elif defined(CONFIG_OV2640_JPEG_SVGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_svga_resolution,
                          OV2640_JPEG_SVGA_RESOUTION_NENTRIES);

#elif defined(CONFIG_OV2640_JPEG_XVGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_xvga_resolution,
                          OV2640_JPEG_XVGA_RESOUTION_NENTRIES);

#elif defined(CONFIG_OV2640_JPEG_SXVGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_sxvga_resolution,
                          OV2640_JPEG_SXVGA_RESOUTION_NENTRIES);

#elif defined(CONFIG_OV2640_JPEG_UXGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_jpeg_uxga_resolution,
                          OV2640_JPEG_UXGA_RESOUTION_NENTRIES);

#else
#  error Unspecified JPEG resolution
#endif

  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

#else /* CONFIG_OV2640_JPEG */

  /* Setup initial register values */

  ret = ov2640_putreglist(i2c, g_ov2640_initialregs,
                          OV2640_INITIALREGS_NENTRIES);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

  /* Setup image resolution */

  ret = ov2640_putreglist(i2c, g_ov2640_resolution_common,
                          OV2640_RESOLUTION_COMMON_NENTRIES);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

#if defined(CONFIG_OV2640_QCIF_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_qcif_resolution,
                          OV2640_QCIF_RESOLUTION_NENTRIES);

#elif defined(CONFIG_OV2640_QVGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_qvga_resolution,
                          OV2640_QVGA_RESOLUTION_NENTRIES);

#elif defined(CONFIG_OV2640_CIF_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_cif_resolution,
                          OV2640_CIF_RESOLUTION_NENTRIES);

#elif defined(CONFIG_OV2640_VGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_vga_resolution,
                          OV2640_VGA_RESOLUTION_NENTRIES);

#elif defined(CONFIG_OV2640_SVGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_svga_resolution,
                          OV2640_SVGA_RESOLUTION_NENTRIES);

#elif defined(CONFIG_OV2640_XGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_xga_resolution,
                          OV2640_XGA_RESOLUTION_NENTRIES);

#elif defined(CONFIG_OV2640_SXGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_sxga_resolution,
                          OV2640_SXGA_RESOLUTION_NENTRIES);

#elif defined(CONFIG_OV2640_UXGA_RESOLUTION)
  ret = ov2640_putreglist(i2c, g_ov2640_uxga_resolution,
                          OV2640_UXGA_RESOLUTION_NENTRIES);

#else
#  error Unknown image resolution
#endif

  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

/* Color format register settings */

  ret = ov2640_putreglist(i2c, g_ov2640_colorfmt_common,
                    OV2640_COLORFMT_COMMON_NENTRIES);
  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

#if defined(CONFIG_OV2640_YUV422_COLORFMT)
  ret = ov2640_putreglist(i2c, g_ov2640_yuv422_colorfmt,
                    OV2640_YUV422_COLORFMT_NENTRIES);

#elif defined(CONFIG_OV2640_RGB565_COLORFMT)
  ret = ov2640_putreglist(i2c, g_ov2640_rgb565_colorfmt,
                    OV2640_RGB565_COLORFMT_NENTRIES);

#else
#  error Unknown color format
#endif

  if (ret < 0)
    {
      gdbg("ERROR: ov2640_putreglist failed: %d\n", ret);
      goto errout;
    }

#endif /* CONFIG_OV2640_JPEG */

  return OK;

errout:
  gdbg("ERROR: Failed to initialize the OV2640: %d\n", ret);
  (void)ov2640_reset(i2c);
  return ret;
}
Ejemplo n.º 17
0
int
I2C::init()
{
	int ret = OK;
	unsigned bus_index;

	// attach to the i2c bus
	_dev = up_i2cinitialize(_bus);

	if (_dev == nullptr) {
		debug("failed to init I2C");
		ret = -ENOENT;
		goto out;
	}

	// the above call fails for a non-existing bus index,
	// so the index math here is safe.
	bus_index = _bus - 1;

	// abort if the max frequency we allow (the frequency we ask)
	// is smaller than the bus frequency
	if (_bus_clocks[bus_index] > _frequency) {
		(void)up_i2cuninitialize(_dev);
		_dev = nullptr;
		log("FAIL: too slow for bus #%u: %u KHz, device max: %u KHz)",
			_bus, _bus_clocks[bus_index] / 1000, _frequency / 1000);
		ret = -EINVAL;
		goto out;
	}

	// set the bus frequency on the first access if it has
	// not been set yet
	if (_bus_clocks[bus_index] == 0) {
		_bus_clocks[bus_index] = _frequency;
	}

	// set frequency for this instance once to the bus speed
	// the bus speed is the maximum supported by all devices on the bus,
	// as we have to prioritize performance over compatibility.
	// If a new device requires a lower clock speed, this has to be
	// manually set via "fmu i2c <bus> <clock>" before starting any
	// drivers.
	// This is necessary as automatically lowering the bus speed
	// for maximum compatibility could induce timing issues on
	// critical sensors the adopter might be unaware of.
	I2C_SETFREQUENCY(_dev, _bus_clocks[bus_index]);

	// call the probe function to check whether the device is present
	ret = probe();

	if (ret != OK) {
		debug("probe failed");
		goto out;
	}

	// do base class init, which will create device node, etc
	ret = CDev::init();

	if (ret != OK) {
		debug("cdev init failed");
		goto out;
	}

	// tell the world where we are
	log("on I2C bus %d at 0x%02x (bus: %u KHz, max: %u KHz)",
		_bus, _address, _bus_clocks[bus_index] / 1000, _frequency / 1000);

out:
	if ((ret != OK) && (_dev != nullptr)) {
		up_i2cuninitialize(_dev);
		_dev = nullptr;
	}
	return ret;
}
Ejemplo n.º 18
0
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_dev_s *dev, unsigned int devno)
#endif
{
  FAR struct ssd1306_dev_s  *priv = &g_oleddev;

  lcdvdbg("Initializing\n");
  DEBUGASSERT(spi && devno == 0);

#ifdef CONFIG_LCD_SSD1306_SPI
  priv->spi = dev;

  /* If this SPI bus is not shared, then we can config it now.
   * If it is shared, then other device could change our config,
   * then just configure before sending data.
   */

#  ifdef CONFIG_SPI_OWNBUS
    /* Configure SPI */

    SPI_SETMODE(priv->spi, CONFIG_SSD1306_SPIMODE);
    SPI_SETBITS(priv->spi, 8);
    SPI_SETFREQUENCY(priv->spi, CONFIG_SSD1306_FREQUENCY);
#  else
    /* Configure the SPI */

    ssd1306_configspi(priv->spi);
#  endif

#else
  /* Remember the I2C configuration */

  priv->i2c  = dev;
  priv->addr = CONFIG_SSD1306_I2CADDR;

  /* Set the I2C address and frequency.  REVISIT:  This logic would be
   * insufficient if we share the I2C bus with any other devices that also
   * modify the address and frequency.
   */

  I2C_SETADDRESS(priv->i2c, CONFIG_SSD1306_I2CADDR, 7);
  I2C_SETFREQUENCY(priv->i2c, CONFIG_SSD1306_I2CFREQ);
#endif

  /* Lock and select device */

  ssd1306_select(priv, true);

  /* Select command transfer */

  ssd1306_cmddata(priv, true);

  /* Configure OLED SPI or I/O, must be delayed 1-10ms */

  up_mdelay(5);

  /* Configure the device */

  ssd1306_sendbyte(priv, SSD1306_DISPOFF);         /* Display off 0xae */
  ssd1306_sendbyte(priv, SSD1306_SETCOLL(0));      /* Set lower column address 0x00 */
  ssd1306_sendbyte(priv, SSD1306_SETCOLH(0));      /* Set higher column address 0x10 */
  ssd1306_sendbyte(priv, SSD1306_STARTLINE(0));    /* Set display start line 0x40 */
  /* ssd1306_sendbyte(priv, SSD1306_PAGEADDR(0));*//* Set page address  (Can ignore)*/
  ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE);   /* Contrast control 0x81 */
  ssd1306_sendbyte(priv,SSD1306_CONTRAST(SSD1306_DEV_CONTRAST));  /* Default contrast 0xCF */
  ssd1306_sendbyte(priv, SSD1306_REMAPPLEFT);      /* Set segment remap left 95 to 0 | 0xa1 */
  /* ssd1306_sendbyte(priv, SSD1306_EDISPOFF); */  /* Normal display off 0xa4 (Can ignore)*/
  ssd1306_sendbyte(priv, SSD1306_NORMAL);          /* Normal (un-reversed) display mode 0xa6 */
  ssd1306_sendbyte(priv, SSD1306_MRATIO_MODE);     /* Multiplex ratio 0xa8 */
  ssd1306_sendbyte(priv, SSD1306_MRATIO(SSD1306_DEV_DUTY));  /* Duty = 1/64 or 1/32 */
  /* ssd1306_sendbyte(priv, SSD1306_SCANTOCOM0);*/ /* Com scan direction: Scan from COM[n-1] to COM[0] (Can ignore)*/
  ssd1306_sendbyte(priv, SSD1306_DISPOFFS_MODE);   /* Set display offset 0xd3 */
  ssd1306_sendbyte(priv, SSD1306_DISPOFFS(0));
  ssd1306_sendbyte(priv, SSD1306_CLKDIV_SET);      /* Set clock divider 0xd5*/
  ssd1306_sendbyte(priv, SSD1306_CLKDIV(8,0));     /* 0x80*/

  ssd1306_sendbyte(priv, SSD1306_CHRGPER_SET);     /* Set pre-charge period 0xd9 */
  ssd1306_sendbyte(priv, SSD1306_CHRGPER(0x0f,1)); /* 0xf1 or 0x22 Enhanced mode */

  ssd1306_sendbyte(priv, SSD1306_CMNPAD_CONFIG);   /* Set common pads / set com pins hardware configuration 0xda */
  ssd1306_sendbyte(priv, SSD1306_CMNPAD(SSD1306_DEV_CMNPAD)); /* 0x12 or 0x02 */

  ssd1306_sendbyte(priv, SSD1306_VCOM_SET);        /* set vcomh 0xdb*/
  ssd1306_sendbyte(priv, SSD1306_VCOM(0x40));

  ssd1306_sendbyte(priv, SSD1306_CHRPUMP_SET);     /* Set Charge Pump enable/disable 0x8d ssd1306 */
  ssd1306_sendbyte(priv, SSD1306_CHRPUMP_ON);      /* 0x14 close 0x10 */

  /* ssd1306_sendbyte(priv, SSD1306_DCDC_MODE); */ /* DC/DC control mode: on (SSD1306 Not supported) */
  /* ssd1306_sendbyte(priv, SSD1306_DCDC_ON); */

  ssd1306_sendbyte(priv, SSD1306_DISPON);          /* Display ON 0xaf */

  /* De-select and unlock the device */

  ssd1306_select(priv, false);

  /* Clear the display */

  up_mdelay(100);
  ssd1306_fill(&priv->dev, SSD1306_Y1_BLACK);
  return &priv->dev;
}