Example #1
0
/** ISR to manage the reception of data from the serial port, placing received bytes into a circular buffer
 *  for later transmission to the host.
 */
ISR(USART1_UDRE_vect, ISR_BLOCK)
{
  if (ringbuf_elements(&USBtoUSART_Buffer))
    UDR1 = ringbuf_get(&USBtoUSART_Buffer);
  else
    UCSR1B &= ~(1 << UDRIE1);
}
Example #2
0
/*---------------------------------------------------------------------------*/
void
uart1_writeb(unsigned char c)
{
  watchdog_periodic();
#if TX_WITH_INTERRUPT

  /* Put the outgoing byte on the transmission buffer. If the buffer
     is full, we just keep on trying to put the byte into the buffer
     until it is possible to put it there. */
  while(ringbuf_put(&txbuf, c) == 0);

  /* If there is no transmission going, we need to start it by putting
     the first byte into the UART. */
  if(transmitting == 0) {
    transmitting = 1;
    UCA0TXBUF = ringbuf_get(&txbuf);
  }

#else /* TX_WITH_INTERRUPT */

 /* Loop until the transmission buffer is available. */
  while(!(IFG2 & UCA0TXIFG));    // Wait for TX buffer ready to receive new byte
        UCA0TXBUF = c; //c;            // Output character
#endif /* TX_WITH_INTERRUPT */
}
Example #3
0
size_t rvidcc_read_serial(void *ptr, size_t len)
{
    size_t bytes = ringbuf_available_data(&DCC_TTY_INBUF);
    if (bytes && len)
    {
        if (bytes > len)
            bytes = len;

        ringbuf_get(&DCC_TTY_INBUF, (unsigned char*)ptr, bytes);
#ifdef RVIDCC_RAW
        /* round up to 4 bytes */
        if (bytes & 0x3)
            ringbuf_advance_read(&DCC_TTY_INBUF, ((bytes + 4) & ~0x3));
        else
            ringbuf_advance_read(&DCC_TTY_INBUF, bytes);

        RVIDCC_ENABLE_READ_INTERRUPT;
#else
        ringbuf_advance_read(&DCC_TTY_INBUF, bytes);
#endif
    }
    else
        bytes = 0;

    return bytes;
}
Example #4
0
void usart3_writebuff(unsigned char* buf, int len) {

  while (len) {
    /* check the empty items in the ringbuff */
    while (ringbuf_put(&txbuf, *buf) == 0);
    buf++;
    len--;
#ifndef USART3_TX_USE_DMA1_CH4 
    if (transmitting == 0) {
      transmitting = 1;
      USART3->DR = ringbuf_get(&txbuf);	/* put in UART */
      USART3->CR1 |= USART_CR1_TXEIE;		/* enable TX register empty int */
    }
#else
    if ((DMA1_Stream3->CR & DMA_SxCR_EN ) != DMA_SxCR_EN ) {
      /* set the start address of your data */      
      DMA1_Stream3->M0AR = (uint32_t) txbuf.data + txbuf.get_ptr;

      /* set the length of your data */ 
      DMA1_Stream3->NDTR = (txbuf.put_ptr - txbuf.get_ptr) & txbuf.mask;
      if (DMA1_Stream3->NDTR > (txbuf.mask + 1 - txbuf.get_ptr)) {
    	  DMA1_Stream3->NDTR = txbuf.mask + 1 - txbuf.get_ptr;
      }
      dma_length = DMA1_Stream3->NDTR;
      /* Enable transfer by setting EN bit */
      DMA1_Stream3->CR |= DMA_SxCR_EN;
    }
#endif

  }
}
/**
  * @brief  Handle_USBAsynchXfer
  *         Send data to USB
  * @param  pdev: instance
  * @retval None
  */
static void Handle_USBAsynchXfer (void *pdev)
{
  if(USB_Tx_State != 1)
  {
    u8_t *data_p;
    u16_t len = ringbuf_available_linear(&usb_vcd_ringbuf_tx, &data_p);

    if (len == 0)
    {
      USB_Tx_State = 0; 
      return;
    }
    
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
     APP_Rx_length &= ~0x03;
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
    
    if (len > CDC_DATA_IN_PACKET_SIZE)
    {
      len = CDC_DATA_IN_PACKET_SIZE;
    }
    USB_Tx_State = 1; 

    DCD_EP_Tx (pdev,
               CDC_IN_EP,
               data_p,
               len);
    ringbuf_get(&usb_vcd_ringbuf_tx, 0, len);
  }  
  
}
Example #6
0
File: uart1.c Project: 1uk3/contiki
/*---------------------------------------------------------------------------*/
void
uart1_writeb(unsigned char c)
{
  watchdog_periodic();
#if TX_WITH_INTERRUPT
  /*
   * Put the outgoing byte on the transmission buffer. If the buffer
   * is full, we just keep on trying to put the byte into the buffer
   * until it is possible to put it there.
   */
  while(ringbuf_put(&txbuf, c) == 0);

  /*
   * If there is no transmission going, we need to start it by putting
   * the first byte into the UART.
   */
  if(transmitting == 0) {
    transmitting = 1;
    SC1_DATA = ringbuf_get(&txbuf);
    INT_SC1FLAG = INT_SCTXFREE;
    INT_SC1CFG |= INT_SCTXFREE;
  }
#else /* TX_WITH_INTERRUPT */

  /* Loop until the transmission buffer is available. */
  while((INT_SC1FLAG & INT_SCTXFREE) == 0);

  /* Transmit the data. */
  SC1_DATA = c;

  INT_SC1FLAG = INT_SCTXFREE;
#endif /* TX_WITH_INTERRUPT */
}
Example #7
0
//Interrupt handler
void _SCI3_(void)
{
if (SCI3.SSR.BIT.RDRF) {
  SCI3.SSR.BIT.RDRF = 0;
  reset_imask_ccr();
  if(sci3_input_handler != NULL) {
    if(sci3_input_handler(SCI3.RDR)) {;}
  }
}
else if (SCI3.SSR.BIT.OER || SCI3.SSR.BIT.FER || SCI3.SSR.BIT.PER) {
  SCI3.SCR3.BYTE &= ~0x40;
  SCI3.SCR3.BYTE &= ~0x10;
  SCI3.SSR.BYTE &= ~0x78;
  SCI3.SCR3.BYTE |= 0x10;
  SCI3.SCR3.BYTE |= 0x40;
  reset_imask_ccr();
}
/*else if () {
	}*/
else if (SCI3.SSR.BIT.TEND) {
	if(ringbuf_elements(&txbuf) == 0) {
		transmitting = 0;
		SCI3.SCR3.BYTE &= ~0x04;
	} else {
		SCI3.TDR = ringbuf_get(&txbuf);
		}
	}
}
Example #8
0
/*---------------------------------------------------------------------------*/
void
uart1_writeb(unsigned char c)
{
  watchdog_periodic();
#if TX_WITH_INTERRUPT

  /* Put the outgoing byte on the transmission buffer. If the buffer
     is full, we just keep on trying to put the byte into the buffer
     until it is possible to put it there. */
  while(ringbuf_put(&txbuf, c) == 0);

  /* If there is no transmission going, we need to start it by putting
     the first byte into the UART. */
  if(transmitting == 0) {
    transmitting = 1;

    /* Loop until the transmission buffer is available. */
    /*while((IFG2 & UTXIFG1) == 0);*/
    TXBUF1 = ringbuf_get(&txbuf);
  }

#else /* TX_WITH_INTERRUPT */

  /* Loop until the transmission buffer is available. */
  while((IFG2 & UTXIFG1) == 0);

  /* Transmit the data. */
  TXBUF1 = c;
#endif /* TX_WITH_INTERRUPT */
}
Example #9
0
int uart_receive(uint8_t *buffer, uint32_t count)
{
#ifndef __USE_UART_PORT3__
    fprintf(stderr, "uart: __USE_UART_PORT3__ not defined\n");
    return -1;
#else
    uint32_t i = 0;
    int data = -1;
    rtimer_clock_t start;
    start = RTIMER_NOW();
    for(i = 0; i < count; i++)
    {
        while((data = ringbuf_get(&uart_ring_buffer)) < 0)
        {
            if(current_timeout == NO_TIMEOUT)
                continue;

            if(RTIMER_CLOCK_LT(start + current_timeout, RTIMER_NOW()))
            {
                fprintf(stderr, "uart: Read timed out\n");
                return -1;
            }
        }

        buffer[i] = (uint8_t)data;
    }
    return count;
#endif
}
/**
  * @brief  usbd_audio_DataIn
  *         Data sent on non-control IN endpoint
  * @param  pdev: device instance
  * @param  epnum: endpoint number
  * @retval status
  */
static uint8_t  usbd_cdc_DataIn (void *pdev, uint8_t epnum)
{
  if (USB_Tx_State == 1)
  {
    u8_t *data_p;
    u16_t len = ringbuf_available_linear(&usb_vcd_ringbuf_tx, &data_p);
    if (len == 0)
    {
      USB_Tx_State = 0;
    }
    else 
    {
      if (len > CDC_DATA_IN_PACKET_SIZE){
        len = CDC_DATA_IN_PACKET_SIZE;
      }
      /* Prepare the available data buffer to be sent on IN endpoint */
      DCD_EP_Tx (pdev,
                 CDC_IN_EP,
                 data_p,
                 len);
      ringbuf_get(&usb_vcd_ringbuf_tx, 0, len);
    }
  }  

  return USBD_OK;
}
Example #11
0
int mp_hal_stdin_rx_chr(void) {
    for (;;) {
        int c = ringbuf_get(&input_buf);
        if (c != -1) {
            return c;
        }
        mp_hal_delay_us(1);
    }
}
Example #12
0
ISR(USCIAB0TX, uartA0B0_tx_interrupt)
{
  if(IFG2 & UCA0TXIFG) {
    if(ringbuf_elements(&txbuf) == 0) {
      transmitting = 0;
    } else {
      TXBUF = ringbuf_get(&txbuf);
    }
  }
}
Example #13
0
File: uart1.c Project: 1uk3/contiki
void
uart1_tx_interrupt(void)
{
  if(ringbuf_elements(&txbuf) == 0) {
    transmitting = 0;
    INT_SC1CFG &= ~INT_SCTXFREE;
  } else {
    SC1_DATA = ringbuf_get(&txbuf);
  }
}
Example #14
0
/* get data received by interrupt */
uint8_t xt_host_recv(void)
{
    if (ringbuf_is_empty(&rb)) {
        return 0;
    } else {
        int16_t d = ringbuf_get(&rb);
        XT_DATA_IN();  // ready to receive from keyboard
        return d;
    }
}
ssize_t
IIS328DQ::read(struct file *filp, char *buffer, size_t buflen)
{
	unsigned count = buflen / sizeof(struct accel_report);
	struct accel_report *abuf = reinterpret_cast<struct accel_report *>(buffer);//指针类型强转
	int ret = 0;

	/* buffer must be large enough */
	if (count < 1)
		return -ENOSPC;

	/* if automatic measurement is enabled */
	if (_call_interval > 0) {

		/*
		 * While there is space in the caller's buffer, and reports, copy them.
		 * Note that we may be pre-empted by the measurement code while we are doing this;
		 * we are careful to avoid racing with it.
		 */
		while (count--) {
			if (0 == ringbuf_get(_reports, abuf, sizeof(*abuf))) {
				ret += sizeof(*abuf);
				abuf++;
			}
		}

		/* if there was no data, warn the caller */
		return ret ? ret : -EAGAIN;
	}

	/* manual measurement */
	ringbuf_flush(_reports);
	measure();

	/* measurement will have generated a report, copy it out */
	if (0 == ringbuf_get(_reports, abuf, sizeof(*abuf)))  {
		ret = sizeof(*abuf);
	}

	return ret;
}
Example #16
0
ISR(UART1TX, uart1_tx_interrupt)
{
  ENERGEST_ON(ENERGEST_TYPE_IRQ);

  if(ringbuf_elements(&txbuf) == 0) {
    transmitting = 0;
  } else {
    TXBUF1 = ringbuf_get(&txbuf);
  }

  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
Example #17
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(serial_line_process, ev, data)
{
  static char buf[BUFSIZE];
  static int ptr;

  PROCESS_BEGIN();

  serial_line_event_message = process_alloc_event();


  ptr = 0;

  while(1) {
    /* Fill application buffer until newline or empty */
    
    printf("Inside serial_line_process : serial_line_event_message = %d\n", serial_line_event_message);
  
    int c = ringbuf_get(&rxbuf);
    
    if(c == -1) {
      printf("rxbuf empty, process yeilding\n") ;
      /* Buffer empty, wait for poll */
      PROCESS_YIELD();
    } else {
      if(c != END) {
        if(ptr < BUFSIZE-1) {
          buf[ptr++] = (uint8_t)c;
        } else {
          /* Ignore character (wait for EOL) */
        }
      } else {
        /* Terminate */
        buf[ptr++] = (uint8_t)'\0';

        /* Broadcast event */
   
       printf("Broadcast event serial_line_event_message\n");
       process_post(PROCESS_BROADCAST, serial_line_event_message, buf);

        /* Wait until all processes have handled the serial line event */
        if(PROCESS_ERR_OK ==
          process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL)) {
          PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_CONTINUE);
        }
        ptr = 0;
      }
    }
  }

  PROCESS_END();
}
Example #18
0
static void uart0_handler(void)
{
	register unsigned int isr;
	volatile mml_uart_regs_t *reg_uart = (volatile mml_uart_regs_t*)MML_UART0_IOBASE;
	int status = 0;
	unsigned char c;	

	/** Retrieve ISR */
	isr = reg_uart->isr;
	
	if( isr & (MML_UART_IER_FFTXOIE_MASK | MML_UART_IER_FFTXHIE_MASK) )
	{
		mml_uart_interrupt_clear(MML_UART_DEV0, MML_UART_IER_FFTXOIE_MASK | MML_UART_IER_FFTXHIE_MASK);
		while( 1 )
		{
			mml_uart_port_status(MML_UART_DEV0, &status);
			if( !(status & MML_UART_STATUS_TX_FULL) )
			{
				if( ringbuf_get(&gSendFifo[0], &c) >= 0)
				//if (rb_read_byte(&gSendLb[0], &c))
					reg_uart->dr = c;
				else
					break;
			}
			else
			{
				break;
			}
		}
	}

	if( isr & (MML_UART_IER_FFRXIE_MASK | MML_UART_IER_OVERIE_MASK))
	{
		mml_uart_interrupt_clear(MML_UART_DEV0, MML_UART_IER_FFRXIE_MASK | MML_UART_IER_OVERIE_MASK);

		while( 1 )
		{
			if( mml_uart_read_char(MML_UART_DEV0, &c) == NO_ERROR )
			{
				if( ringbuf_put(&gRevFifo[0], c) < 0) break;
				//if (!rb_write_byte(&gRevLb[0], c)) break;
			}
			else
			{
				break;
			}
		}
	}
}
Example #19
0
void usart3_writeb(unsigned char c) {
//  watchdog_periodic();
  /* Put the outgoing byte on the transmission buffer. If the buffer
     is full, we just keep on trying to put the byte into the buffer
     until it is possible to put it there. */
  while (ringbuf_put(&txbuf, c) == 0);
  
  /* If there is no transmission going, we need to start it by putting
     the first byte into the UART. */
  if (transmitting == 0) {
    transmitting = 1;
    USART3->DR = ringbuf_get(&txbuf);	/* put in UART */
    USART3->CR1 |= USART_CR1_TXEIE;		/* enable TX register empty int */
  }
}
Example #20
0
int mp_hal_stdin_rx_chr(void) {
    for (;;) {
        int c = ringbuf_get(&stdin_ringbuf);
        if (c != -1) {
            return c;
        }
        #if 0
        // Idles CPU but need more testing before enabling
        if (!ets_loop_iter()) {
            asm("waiti 0");
        }
        #else
        mp_hal_delay_us(1);
        #endif
    }
}
Example #21
0
size_t uart0_read(uint8_t *pData, size_t DataSize)
{
	size_t size = 0;
	
	if( (!pData) || (!DataSize)) return 0;

	while( size < DataSize )
	{
		if( ringbuf_get(&gRevFifo[0], pData) < 0) break;
		pData++;
		size++;
	}
	return size;

//	return rb_read(&gRevLb[0], pData, DataSize);
}
Example #22
0
void uart_rx(int length) {
    if (!sock_connected) {
        uart_rx_one_char(UART);
        return;
    }


    int i = 0;
    unsigned char c;
    bool rb_full = false;

    if (xSemaphoreTakeFromISR(ringbuf_mutex, NULL)) {
        while (ringbuf_get(&ringbuf_t, &c) == 0) {
            if (ringbuf_owr(&ringbuf_m, c)) {
                rb_full = true;
            }
        }

        for (i = 0; i < length; i++) {
            if (ringbuf_owr(&ringbuf_m, uart_rx_one_char(UART0))) {
                rb_full = true;
            }
        }
        xSemaphoreGiveFromISR(ringbuf_mutex, NULL);
    } else {
        DBG("uart_rx: failed to take semphr");

        // ringbuf is taken by send task
        // all uart data is copied in temporary ringbuffer that will be copied in main ringbuffer once it is available
        for (i = 0; i < length; i++) {
            if (ringbuf_owr(&ringbuf_t, uart_rx_one_char(UART0))) {
                rb_full = true;
            }
        }
    }

    //DBG("uart_rx: %d b", length);

    // notify send task that there is data to be sent
    xQueueSendToBackFromISR(tx_queue, &length, NULL);

    if (rb_full) {
        // not every byte could be put in one of the two ringbuffers
        // we can just print a message about it
        DBG("uart_rx: ringbuff overflow");
    }
}
int
IIS328DQ::init()
{
	int ret = ERROR;
	
	if (probe() != OK)
		goto out;

	/* do SPI init (and probe) first */
	if (CDev::init() != OK)
		goto out;

	/* allocate basic report buffers */
	if (_reports != NULL) {
        ringbuf_deinit(_reports);
		vPortFree(_reports);
		_reports = NULL;
	}
	/* allocate basic report buffers */
	_reports = (ringbuf_t *) pvPortMalloc (sizeof(ringbuf_t));
	ringbuf_init(_reports, 2, sizeof(accel_report));

	if (_reports == NULL)
		goto out;

	_class_instance = register_class_devname(ACCEL_BASE_DEVICE_PATH);

	reset();

	measure();

	/* advertise sensor topic, measure manually to initialize valid report */
	struct accel_report arp;
	ringbuf_get(_reports, &arp, sizeof(arp));

	_accel_topic = orb_advertise_multi(ORB_ID(sensor_accel), &arp,
		&_orb_class_instance, (is_external()) ? ORB_PRIO_VERY_HIGH : ORB_PRIO_DEFAULT);

	if (_accel_topic == NULL) {
		DEVICE_DEBUG("failed to create sensor_accel publication");
	}

	ret = OK;
out:
	return ret;
}
Example #24
0
ISR(USCIAB0TX, uart0_tx_interrupt)
{
  ENERGEST_ON(ENERGEST_TYPE_IRQ);
  if((IFG2 & UCA0TXIFG)){

    if(ringbuf_elements(&txbuf) == 0) {
      transmitting = 0;
    } else {
      UCA0TXBUF = ringbuf_get(&txbuf);
    }
  }

  /* In a stand-alone app won't work without this. Is the UG misleading? */
  IFG2 &= ~UCA0TXIFG;

  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
Example #25
0
void Jennic_In_Task()
{
  size_t i;

  Endpoint_SelectEndpoint(VirtualSerial_CDC1_Interface.Config.DataINEndpoint.Address);
  if ( !Endpoint_IsINReady() )
    return;

  /* Read bytes from the USART receive buffer and send with CDC */
  /* pass through in programming mode */
  if (ringbuf_elements(&USARTtoUSB_Buffer) && jennic_in_programming_mode)
  {
    uint8_t byte = ringbuf_get(&USARTtoUSB_Buffer);

      if (CDC_Device_SendByte(&VirtualSerial_CDC1_Interface, byte) != ENDPOINT_READYWAIT_NoError)
        return;
  }
}
Example #26
0
/*---------------------------------------------------------------------------*/
static void
uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context)
{
  ENERGEST_ON(ENERGEST_TYPE_IRQ);

  if (p_event->type == NRF_DRV_UART_EVT_RX_DONE) {
    if (uart0_input_handler != NULL) {
      uart0_input_handler(p_event->data.rxtx.p_data[0]);
    }
    (void)nrf_drv_uart_rx(rx_buffer, 1);
  } else if (p_event->type == NRF_DRV_UART_EVT_TX_DONE) {
    if (ringbuf_elements(&txbuf) > 0) {
      uint8_t c = ringbuf_get(&txbuf);
      nrf_drv_uart_tx(&c, 1);
    }
  }

  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
Example #27
0
void write_task(void *pvParameters) {
    int i;
    while (1) {
        if (xQueueReceive(tx_queue, &i, portMAX_DELAY)) {
            if (xSemaphoreTake(ringbuf_mutex, portMAX_DELAY)) {
                int length = ringbuf_m.fill_cnt;
                DBG("net_tx: %d", length);

                unsigned char c;
                for (i = 0; i < length && i < sizeof(tx_buffer_m); i++) {
                    if (ringbuf_get(&ringbuf_m, &c)) {
                        printf("buffer error!\n");
                        break;
                    }
                    tx_buffer_m[i] = c;
                }
                xSemaphoreGive(ringbuf_mutex);
            } else {
                printf("write_task: semphr already taken\n");
            }

            if (write(sta_socket, tx_buffer_m, i) < 0) {
                printf("C > send fail\n");

                //close(sta_socket);
                //sta_socket = 0;

                // socket is closed in read task

                break;
            }
        } else {
            printf("tx: failed to receive from queue\n");
        }
    }

    printf("exiting write task\n");
    vTaskDelete(NULL);
}
Example #28
0
void EP7_IN_Callback (void)
{
  if (USB_Tx_State == 1)
  {
    u8_t *buf;
    int avail = ringbuf_available_linear(&tx_rb, &buf);
    if (avail  == 0) {
      USB_Tx_State = 0;
      return;
    }

    if (avail > VIRTUAL_COM_PORT_DATA_SIZE)
    {
      avail = VIRTUAL_COM_PORT_DATA_SIZE;
    }

    UserToPMABufferCopy(buf, ENDP7_TXADDR, avail);
    ringbuf_get(&tx_rb, 0, avail);
    SetEPTxCount(ENDP7, avail);
    SetEPTxValid(ENDP7);
  }
}
Example #29
0
void USART3_IRQHandler(void)
{
  ENERGEST_ON(ENERGEST_TYPE_IRQ);
  
	/* check if rx register not empty and int enabled */
  if ((USART3->SR & USART_SR_RXNE) && (USART3->CR1 & USART_CR1_RXNEIE)) {
		uint8_t c = USART3->DR;
		if (usart3_input_handler != NULL) {
			usart3_input_handler(c);
		}  
  }
	/* check if tx register empty and int enabled */
  if ((USART3->SR & USART_SR_TXE) && (USART3->CR1 & USART_CR1_TXEIE)) {
		if (ringbuf_elements(&txbuf) == 0) {
			transmitting = 0;
			USART3->CR1 &= ~USART_CR1_TXEIE;
		} else {
			USART3->DR = ringbuf_get(&txbuf);
		}
  }  
  
  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
Example #30
0
/*---------------------------------------------------------------------------*/
static void
cs_isr(uint8_t port, uint8_t pin)
{
  int d, i;

  /* check if ISR comes from CS pin */
  if((port != SPI_CS_PORT) && (pin != SPI_CS_PIN)) {
    return;
  }
  
  /* CS goes HIGH, End of Transmission */
  if(GPIO_READ_PIN(SPI_CS_PORT_BASE, SPI_CS_PIN_MASK)) {
    /* check if something left in RX FIFO after transaction, and put all remain data into RX ringbuffer */
    while(REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE) {
      d = REG(SSI0_BASE + SSI_DR);
      ringbuf_put(&spi_rx_buf, d);
      PRINTF("ERR: Something left in FIFO!\r\n");
    }
    /* pass received  data to upper level driver via callback */
    d = ringbuf_get(&spi_rx_buf);
    while(d != -1) {
      if(input_callback) {
        input_callback((unsigned char)d);
      }
      d = ringbuf_get(&spi_rx_buf);
    }
    /* mark that there is no start of frame phase */
    /* TODO: is it necessary? */
    start_of_frame = 0;
    /* check if TX FIFO is not empty */
    if(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)) {
      /* if TX FIFO is not empty, reset SSI to flush TX FIFO
         it is possible that previous transaction has been failed, so complete frame
         has not been transmitted. Eg. NBR has been turned off during transmission
      */
      PRINTF("ERR: TX FIFO not empty after transaction!\r\n");
      ssi_reset_request = 3;
    }
    if(ssi_reset_request) {
      /* if reset request is active, perform SSI reset */
      PRINTF("WARN: SSI reset request %u\r\n", ssi_reset_request);
      ssi_reconfigure(1);
      ssi_reset_request = 0;
    }
  } else {
    /* CS goes LOW, Start of Transmission */
    start_of_frame = 1;
    /* fill TX FIFO with data only if we were connected */
    if(connected) {
      /* get number of elements in ringbuffer */
      d = ringbuf_elements(&spi_tx_buf);
      /* send that number to master with characteristic upper nibble */
      d = 0x50 | (d > 7 ? 7 : d);
      REG(SSI0_BASE + SSI_DR) = d;
      for(i = 0; i < 7; i++) {
        if(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)) {
          /* Error, we shouldn't overflow TX FIFO */
          PRINTF("ERR: TX FIFO overflow!\r\n");
          break;
        }
        d = ringbuf_get(&spi_tx_buf);
        if(d == -1) {
          REG(SSI0_BASE + SSI_DR) = 0xff;
        } else {
          REG(SSI0_BASE + SSI_DR) = d;
        }
      }
      /* If the CS interrupt was triggered due to slave requesting SPI transfer,
       * we clear the INT pin, as the transfer has now been completed.
       */
      if(ringbuf_elements(&spi_tx_buf) == 0) {
        GPIO_CLR_PIN(SPI_INT_PORT_BASE, SPI_INT_PIN_MASK);
      }
    } else {
      /* mark we are connected */
      connected = 1;
    }
  }
}