bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd)
{
  const uint8_t length = p_aci_cmd->buffer[0];
  bool ret_val = false;

  if (length > HAL_ACI_MAX_LENGTH)
  {
    return false;
  }

  ret_val = aci_queue_enqueue(&aci_tx_q, p_aci_cmd);
  if (ret_val)
  {
    if(!aci_queue_is_full(&aci_rx_q))
    {
      // Lower the REQN only when successfully enqueued
      m_aci_reqn_enable();
    }

    if (aci_debug_print)
    {
      Serial.print("C"); //ACI Command
      m_aci_data_print(p_aci_cmd);
    }
  }

  return ret_val;
}
bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data)
{
  bool was_full;

#ifdef HAL_ACI_TL_INTERRUPT
  if (!a_pins_local_ptr->interface_is_interrupt && !aci_queue_is_full(&aci_rx_q))
#else
  if (!aci_queue_is_full(&aci_rx_q))
#endif
  {
    m_aci_event_check();
  }

  was_full = aci_queue_is_full(&aci_rx_q);

  if (aci_queue_dequeue(&aci_rx_q, p_aci_data))
  {
#ifdef HAL_ACI_TL_DEBUG
    if (aci_debug_print)
    {
      Serial.print(" E");
      m_aci_data_print(p_aci_data);
    }
#endif

#ifdef HAL_ACI_TL_INTERRUPT
    if (was_full && a_pins_local_ptr->interface_is_interrupt)
	  {
      /* Enable RDY line interrupt again */
      attachInterrupt(a_pins_local_ptr->interrupt_number, m_aci_isr, LOW);
#if defined(SPI_HAS_TRANSACTION) && defined(__SAMD21G18A__)
      SPI.usingInterrupt(a_pins->interrupt_number);
#endif
    }
#endif

    /* Attempt to pull REQN LOW since we've made room for new messages */
    if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q))
    {
      m_aci_reqn_enable();
    }

    return true;
  }

  return false;
}
bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data)
{
  bool was_full;

  if (!a_pins_local_ptr->interface_is_interrupt && !aci_queue_is_full(&aci_rx_q))
  {
    m_aci_event_check();
  }

  was_full = aci_queue_is_full(&aci_rx_q);

  if (aci_queue_dequeue(&aci_rx_q, p_aci_data))
  {
    if (aci_debug_print)
    {
      Serial.print(" E");
      m_aci_data_print(p_aci_data);
    }

    if (was_full && a_pins_local_ptr->interface_is_interrupt)
	  {
      /* Enable RDY line interrupt again */
      attachInterrupt(a_pins_local_ptr->interrupt_number, m_aci_isr, LOW);
    }

    /* Attempt to pull REQN LOW since we've made room for new messages */
    if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q))
    {
      m_aci_reqn_enable();
    }

    return true;
  }

  return false;
}
Ejemplo n.º 4
0
void hal_aci_tl_init(aci_pins_t *a_pins, bool debug)
{
  aci_debug_print = debug;

  /* Needs to be called as the first thing for proper intialization*/
  m_aci_pins_set(a_pins);

  /*
  The SPI lines used are mapped directly to the hardware SPI
  MISO MOSI and SCK
  Change here if the pins are mapped differently

  The SPI library assumes that the hardware pins are used
  */
  spi_master_init(a_pins->spi);
  
  struct spi_device spi_device_conf = {
    .id = a_pins->reqn_pin
  };
  
  spi_master_setup_device(a_pins->spi, &spi_device_conf, SPI_MODE_0, BLUETOOTH_DATA_RATE, 0);
  
  //Board dependent defines
  #if defined (__AVR__)
    //For Arduino use the LSB first
    a_pins->spi->CTRL |= SPI_DORD_bm;
  #elif defined(__PIC32MX__)
    //For ChipKit use MSBFIRST and REVERSE the bits on the SPI as LSBFIRST is not supported
    SPI.setBitOrder(MSBFIRST);
  #endif

  /* Initialize the ACI Command queue. This must be called after the delay above. */
  aci_queue_init(&aci_tx_q);
  aci_queue_init(&aci_rx_q);

  //Configure the IO lines
  //pinMode(a_pins->rdyn_pin,		INPUT_PULLUP);
  //pinMode(a_pins->reqn_pin,		OUTPUT);
  
  spi_enable(a_pins->spi);
  
  if (UNUSED != a_pins->active_pin)
  {
    pinMode(a_pins->active_pin,	INPUT);
  }
  
  /* Pin reset the nRF8001, required when the nRF8001 setup is being changed */
  hal_aci_tl_pin_reset();

  /* Set the nRF8001 to a known state as required by the datasheet*/
  digitalWrite(a_pins->miso_pin, 0);
  digitalWrite(a_pins->mosi_pin, 0);
  digitalWrite(a_pins->reqn_pin, 1);
  digitalWrite(a_pins->sck_pin,  0);

  delay(30); //Wait for the nRF8001 to get hold of its lines - the lines float for a few ms after the reset

  /* Attach the interrupt to the RDYN line as requested by the caller */
  if (a_pins->interface_is_interrupt)
  {
    // We use the LOW level of the RDYN line as the atmega328 can wakeup from sleep only on LOW
    attachInterrupt(a_pins->interrupt_number, m_aci_isr, LOW);
  }
}

bool hal_aci_tl_send(hal_aci_data_t *p_aci_cmd)
{
  const uint8_t length = p_aci_cmd->buffer[0];
  bool ret_val = false;

  if (length > HAL_ACI_MAX_LENGTH)
  {
    return false;
  }

  ret_val = aci_queue_enqueue(&aci_tx_q, p_aci_cmd);
  if (ret_val)
  {
    if(!aci_queue_is_full(&aci_rx_q))
    {
      // Lower the REQN only when successfully enqueued
      m_aci_reqn_enable();
    }

    if (aci_debug_print)
    {
      //Serial.print("C"); //ACI Command
      m_aci_data_print(p_aci_cmd);
    }
  }

  return ret_val;
}

static uint8_t spi_readwrite(const uint8_t aci_byte)
{
	//Board dependent defines
#if defined (__AVR__)
    //For Arduino the transmission does not have to be reversed
    return spi_readwrite_xmega(aci_byte);
#elif defined(__PIC32MX__)
    //For ChipKit the transmission has to be reversed
    uint8_t tmp_bits;
    tmp_bits = SPI.transfer(REVERSE_BITS(aci_byte));
	return REVERSE_BITS(tmp_bits);
#endif
}

bool hal_aci_tl_rx_q_empty (void)
{
  return aci_queue_is_empty(&aci_rx_q);
}

bool hal_aci_tl_rx_q_full (void)
{
  return aci_queue_is_full(&aci_rx_q);
}

bool hal_aci_tl_tx_q_empty (void)
{
  return aci_queue_is_empty(&aci_tx_q);
}

bool hal_aci_tl_tx_q_full (void)
{
  return aci_queue_is_full(&aci_tx_q);
}

void hal_aci_tl_q_flush (void)
{
  m_aci_q_flush();
}