2013年12月26日 星期四

nrf9160 soft uart - using gpio simulator uart

 static uint32_t get_BitWidth(uint32_t baudrate)
{
  uint32_t bit_width;

  switch( baudrate )
  {
    case 4800:
      bit_width = 0x7c; //123~152 for 4800, for nrf9160
      break;

    case 9600:
      bit_width = 0x68; //104
      break;

    case 19200:
      bit_width = 0x34; //52
      break;
 
    case 38400:
      bit_width = 0x1a; //26
      break;
 
    case 57600:
      bit_width = 0x11; //17
      break;
 
    case 115200:
      bit_width = 0x9;
      break;
 
    default:
      bit_width = ( 650000 / baudrate ) + 1; //for urf9160
      break;
  }

  return bit_width;
}

void Soft_Uart_Send(char* data, uint32_t len)
{
  k_mutex_lock(&s_softuarte_send_mutex, K_FOREVER);
  char      c;
  uint32_t  i,j;

  for ( i = 0; i < len; i++ )
  {
      c = data[i];
      // pull down as start bit
      //GPIO_WRITE_LOW( gpio_port_tx, gpio_mask_tx );
      nrf_gpio_pin_write(s_tx_pin, 0);
      //delay_us(bit_width);
      k_usleep(s_delay_width);

      for ( j = 0; j < 8; j++ )
      {
          if ( c & 0x01 )
          {
              //GPIO_WRITE_HIGH( gpio_port_tx, gpio_mask_tx );
              nrf_gpio_pin_write(s_tx_pin, 1);
          }
          else
          {
              //GPIO_WRITE_LOW( gpio_port_tx, gpio_mask_tx );
              nrf_gpio_pin_write(s_tx_pin, 0);
          }
          //delay_us(bit_width);
          k_usleep(s_delay_width+0x02); //0x02 for run mode
          c >>= 1;
      }

      // pull high as stop bit
      //GPIO_WRITE_HIGH( gpio_port_tx, gpio_mask_tx );
      nrf_gpio_pin_write(s_tx_pin, 1);
      //delay_us(bit_width);
      k_usleep(s_delay_width);

      if( data[i] == 0x0a )
      {
        c = 0x0d; //return
        Soft_Uart_Send(&c, 1);
      }
  }

  k_mutex_unlock(&s_softuarte_send_mutex);
}

void Soft_Uart_Recv(char* data, uint32_t len, uint32_t timeout)
{
  k_mutex_lock(&s_softuarte_recv_mutex, K_FOREVER);

  uint32_t  i,j;
  uint32_t  c;
  uint8_t   b[8];
  uint32_t  input[1];
  uint32_t  starttime = k_uptime_get_32();
 
 
  for ( i = 0; i < len; i++ )
  {
      c = 0;
      memset(b, 0, sizeof(b));
      
      // wait for start bit, first interrupt come in no wait
      if( i > 0 )
      {
        while ( nrf_gpio_pin_read(s_rx_pin) > 0x0 )
        {
          if( k_uptime_get_32() - starttime >= timeout )
            break;
        }

        k_usleep(s_delay_width/4);
      }
            
      for ( j = 0; j < 8; j++ )
      {
          k_usleep(s_delay_width);
          b[j] = ( nrf_gpio_pin_read(s_rx_pin) ) ? 1 : 0;
      }
 
      for ( int j = 0; j < 8; j++ )
      {
          c |= (b[j] << j);
      }
      data[i] = c;

      // wait for stop bit
      while ( nrf_gpio_pin_read(s_rx_pin) == 0x0 )
      {
        if( k_uptime_get_32() - starttime >= timeout )
          break;
      }
  }

  k_mutex_unlock(&s_softuarte_recv_mutex);
}

void Init_SoftUart(uint32_t rx_pin, uint32_t tx_pin, uint32_t baudrate)
{
  int err;
   
  nrfx_gpiote_in_config_t in_config =
  {
    .sense            = NRF_GPIOTE_POLARITY_HITOLO,
    .pull             = NRF_GPIO_PIN_PULLUP,
    .is_watcher       = false,
    .hi_accuracy      = true,
    .skip_gpio_setup  = true
  };

  nrfx_gpiote_out_config_t out_config =
  {
    .action     = NRF_GPIOTE_POLARITY_TOGGLE,
    .init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH,
    .task_pin   = false
  };

  s_rx_pin = rx_pin;
  s_tx_pin = tx_pin;

  IRQ_DIRECT_CONNECT(GPIOTE0_IRQn, 0, nrfx_gpiote_irq_handler, 0);
  irq_enable(GPIOTE0_IRQn);

  err = nrfx_gpiote_init(0);
  if (err != NRFX_SUCCESS)
  {
    printk("nrfx_gpiote_init error: %08x", err);
    return;
  }
   
  err = nrfx_gpiote_in_init(s_rx_pin, &in_config, rx_event_handler);
  if (err != NRFX_SUCCESS)
  {
    printk("nrfx_gpiote_in_init error: %08x", err);
    return;
  }

  if( out_config.task_pin == true )
  {
    err = nrfx_gpiote_out_init(s_tx_pin, &out_config);
    if (err != NRFX_SUCCESS)
    {
      printk("nrfx_gpiote_out_init error: %08x", err);
      return;
    }
  }
   
  nrf_gpio_cfg(s_rx_pin,
              NRF_GPIO_PIN_DIR_INPUT,
              NRF_GPIO_PIN_INPUT_CONNECT,
              NRF_GPIO_PIN_PULLUP,
              NRF_GPIO_PIN_H0H1,
              NRF_GPIO_PIN_NOSENSE);

  nrf_gpio_cfg(s_tx_pin,
              NRF_GPIO_PIN_DIR_OUTPUT,
              NRF_GPIO_PIN_INPUT_DISCONNECT,
              NRF_GPIO_PIN_PULLUP,
              NRF_GPIO_PIN_H0H1,
              NRF_GPIO_PIN_NOSENSE);

  nrfx_gpiote_in_event_enable(s_rx_pin, true);

  if( out_config.task_pin == true )
  {
    nrfx_gpiote_out_task_enable(s_tx_pin);
  }
 
  s_delay_width = get_BitWidth(baudrate);

  s_softuart_work = 1;
  k_thread_create(&s_kthread_softuart, //local kthread_softuart will crash in k_sleep
                  stack_softuart,
                  THREAD_STACKSIZE,
                  SoftUart_Thread,
                  NULL,
                  NULL,
                  NULL,
                  -1,
                  K_INHERIT_PERMS,
                  K_NO_WAIT);
}

source download:
https://www.mediafire.com/file/gdzxlryiwbfnwdz/nrf9160_softuart.zip

沒有留言:

張貼留言