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;
}
Example #2
0
/*
  Checks the RDYN line and runs the SPI transfer if required.
*/
static void m_aci_event_check(void)
{
  hal_aci_data_t data_to_send;
  hal_aci_data_t received_data;

  // No room to store incoming messages
  if (aci_queue_is_full(&aci_rx_q))
  {
    return;
  }

  // If the ready line is disabled and we have pending messages outgoing we enable the request line
  if (HIGH == mraa_gpio_read (a_pins_local_ptr->m_rdy_ctx))
  // if (HIGH == digitalRead(a_pins_local_ptr->rdyn_pin))
  {
    if (!aci_queue_is_empty(&aci_tx_q))
    {
      m_aci_reqn_enable();
    }

    return;
  }

  // Receive from queue
  if (!aci_queue_dequeue(&aci_tx_q, &data_to_send))
  {
    /* queue was empty, nothing to send */
    data_to_send.status_byte = 0;
    data_to_send.buffer[0] = 0;
  }

  // Receive and/or transmit data
  m_aci_spi_transfer(&data_to_send, &received_data);

  /* If there are messages to transmit, and we can store the reply, we request a new transfer */
  if (!aci_queue_is_full(&aci_rx_q) && !aci_queue_is_empty(&aci_tx_q))
  {
    m_aci_reqn_enable();
  }

  // Check if we received data
  if (received_data.buffer[0] > 0)
  {
    if (!aci_queue_enqueue(&aci_rx_q, &received_data))
    {
      /* Receive Buffer full.
         Should never happen.
         Spin in a while loop.
      */
      while(1);
    }
  }

  return;
}
Example #3
0
void lib_aci_board_init(aci_state_t *aci_stat)
{
    hal_aci_evt_t *aci_data = NULL;
    aci_data = (hal_aci_evt_t *)&msg_to_send;

    if (REDBEARLAB_SHIELD_V1_1 == aci_stat->aci_pins.board_name)
    {
      /*
      The Bluetooth low energy Arduino shield v1.1 requires about 100ms to reset.
      This is not required for the nRF2740, nRF2741 modules
      */
      usleep(100000);

      /*
      Send the soft reset command to the nRF8001 to get the nRF8001 to a known state.
      */
      lib_aci_radio_reset();

      while (1)
      {
        /*Wait for the command response of the radio reset command.
        as the nRF8001 will be in either SETUP or STANDBY after the ACI Reset Radio is processed
        */


        if (true == lib_aci_event_get(aci_stat, aci_data))
        {
          aci_evt_t * aci_evt;
          aci_evt = &(aci_data->evt);

          if (ACI_EVT_CMD_RSP == aci_evt->evt_opcode)
          {
                if (ACI_STATUS_ERROR_DEVICE_STATE_INVALID == aci_evt->params.cmd_rsp.cmd_status) //in SETUP
                {
                    //Inject a Device Started Event Setup to the ACI Event Queue
                    msg_to_send.buffer[0] = 4;    //Length
                    msg_to_send.buffer[1] = 0x81; //Device Started Event
                    msg_to_send.buffer[2] = 0x02; //Setup
                    msg_to_send.buffer[3] = 0;    //Hardware Error -> None
                    msg_to_send.buffer[4] = 2;    //Data Credit Available
                    aci_queue_enqueue(&aci_rx_q, &msg_to_send);
                }
                else if (ACI_STATUS_SUCCESS == aci_evt->params.cmd_rsp.cmd_status) //We are now in STANDBY
                {
                    //Inject a Device Started Event Standby to the ACI Event Queue
                    msg_to_send.buffer[0] = 4;    //Length
                    msg_to_send.buffer[1] = 0x81; //Device Started Event
                    msg_to_send.buffer[2] = 0x03; //Standby
                    msg_to_send.buffer[3] = 0;    //Hardware Error -> None
                    msg_to_send.buffer[4] = 2;    //Data Credit Available
                    aci_queue_enqueue(&aci_rx_q, &msg_to_send);
                }
                else if (ACI_STATUS_ERROR_CMD_UNKNOWN == aci_evt->params.cmd_rsp.cmd_status) //We are now in TEST
                {
                    //Inject a Device Started Event Test to the ACI Event Queue
                    msg_to_send.buffer[0] = 4;    //Length
                    msg_to_send.buffer[1] = 0x81; //Device Started Event
                    msg_to_send.buffer[2] = 0x01; //Test
                    msg_to_send.buffer[3] = 0;    //Hardware Error -> None
                    msg_to_send.buffer[4] = 0;    //Data Credit Available
                    aci_queue_enqueue(&aci_rx_q, &msg_to_send);
                }

                printf ("BREAK\n");
                //Break out of the while loop
                break;
          }
          else
          {
            //Serial.println(F("Discard any other ACI Events"));
          }

        }
      }
    }
}
Example #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();
}