Ejemplo n.º 1
0
Archivo: uhi_cdc.c Proyecto: marekr/asf
static void uhi_cdc_tx_send(
		usb_add_t add,
		usb_ep_t ep,
		uhd_trans_status_t status,
		iram_size_t nb_transferred)
{
	uint8_t port = 0;
	uhi_cdc_port_t *ptr_port;
	uhi_cdc_line_t *line;
	uhi_cdc_buf_t *buf;
	irqflags_t flags;
	UNUSED(add);

	flags = cpu_irq_save();

	// Search port corresponding at endpoint
	while (1) {
		ptr_port = uhi_cdc_get_port(port++);
		if (ptr_port == NULL) {
			cpu_irq_restore(flags);
			return;
		}
		line = &ptr_port->line_tx;
		if (ep == line->ep_data) {
			break; // Port found
		}
	}

	if (UHD_TRANS_NOERROR != status) {
		// Abort transfer
		line->b_trans_ongoing  = false;
		cpu_irq_restore(flags);
		return;
	}

	// Update SOF tag, if it is a short packet
	if (nb_transferred != line->buffer_size) {
		if (uhi_cdc_dev.dev->speed == UHD_SPEED_HIGH) {
			line->sof = uhd_get_microframe_number();
		} else {
			line->sof = uhd_get_frame_number();
		}
	}

	// Update buffer structure
	buf = &line->buffer[(line->buf_sel == 0) ? 1 : 0 ];
	buf->nb = 0;
	line->b_trans_ongoing  = false;
	cpu_irq_restore(flags);

	// Manage new transfer
	uhi_cdc_tx_update(line);
}
Ejemplo n.º 2
0
Archivo: uhi_cdc.c Proyecto: marekr/asf
static bool uhi_cdc_tx_update(uhi_cdc_line_t *line)
{
	irqflags_t flags;
	uhi_cdc_buf_t *buf;

	flags = cpu_irq_save();
	// Check if transfer is already on-going
	if (line->b_trans_ongoing) {
		cpu_irq_restore(flags);
		return false;
	}
	// Check if transfer must be delayed after the next SOF
	if (uhi_cdc_dev.dev->speed == UHD_SPEED_HIGH) {
		if (line->sof == uhd_get_microframe_number()) {
			cpu_irq_restore(flags);
			return false;
		}
	} else {
		if (line->sof == uhd_get_frame_number()) {
			cpu_irq_restore(flags);
			return false;
		}
	}

	// Send the current buffer if not empty
	buf = &line->buffer[line->buf_sel];
	if (buf->nb == 0) {
		cpu_irq_restore(flags);
		return false;
	}

	// Change current buffer to next buffer
	line->buf_sel = (line->buf_sel == 0)? 1 : 0;

	// Start transfer
	line->b_trans_ongoing = true;
	cpu_irq_restore(flags);

	return uhd_ep_run(
		uhi_cdc_dev.dev->address,
		line->ep_data,
		true,
		buf->ptr,
		buf->nb,
		1000,
		uhi_cdc_tx_send);
}
Ejemplo n.º 3
0
static void uhi_midi_rx_received(
usb_add_t add,
usb_ep_t ep,
uhd_trans_status_t status,
iram_size_t nb_transferred)
{
	uhi_midi_line_t *line;
	uhi_midi_buf_t *buf;

	UNUSED(add);

	// Search port corresponding at endpoint - (used to be searching port (when it was CDC), now just sets the transmission line to the one we know)
	line = &(uhi_midi_dev.line_rx);
  
	if ((UHD_TRANS_TIMEOUT == status) && nb_transferred) {
		//LED_On(LED5);
		line->b_trans_ongoing  = false;
		return;
		// this used to not return, it went on and saved the bytes even in the case of a timeout. That caused the software to constantly think it was getting new data even though they were just timeouts.
	}
	else if (UHD_TRANS_NOERROR != status) {
		// Abort transfer
		LED_On(LED5);
		line->b_trans_ongoing  = false;
		return;
	}
	LED_Off(LED5);
	// Update SOF tag, if it is a short packet
	if (nb_transferred != line->buffer_size) {
		if (uhi_midi_dev.dev->speed == UHD_SPEED_HIGH) {
			line->sof = uhd_get_microframe_number();
			} else {
			line->sof = uhd_get_frame_number();
		}
	}
	
	// Update buffer structure
	buf = &line->buffer[(line->buf_sel == 0) ? 1 : 0];
	buf->pos = 0;
	buf->nb = nb_transferred;
	line->b_trans_ongoing  = false;
	// Manage new transfer
	// note that rx_update calls this function, or at least sets up the endpoint transfer that will call this function when it is done. 
	uhi_midi_rx_update(line);
}
Ejemplo n.º 4
0
Archivo: uhi_cdc.c Proyecto: marekr/asf
static bool uhi_cdc_rx_update(uhi_cdc_line_t *line)
{
	irqflags_t flags;
	uhi_cdc_buf_t *buf_nosel;
	uhi_cdc_buf_t *buf_sel;

	flags = cpu_irq_save();
	// Check if transfer is already on-going
	if (line->b_trans_ongoing) {
		cpu_irq_restore(flags);
		return false;
	}

	// Search a empty buffer to start a transfer
	buf_sel = &line->buffer[line->buf_sel];
	buf_nosel = &line->buffer[(line->buf_sel == 0)? 1 : 0];
	if (buf_sel->pos >= buf_sel->nb) {
		// The current buffer has been read
		// then reset it
		buf_sel->pos = 0;
		buf_sel->nb = 0;
	}
	if (!buf_sel->nb && buf_nosel->nb) {
		// New data available then change current buffer
		line->buf_sel = (line->buf_sel == 0)? 1 : 0;
		buf_nosel = buf_sel;
		UHI_CDC_RX_NOTIFY();
	}

	if (buf_nosel->nb) {
		// No empty buffer available to start a transfer
		cpu_irq_restore(flags);
		return false;
	}

	// Check if transfer must be delayed after the next SOF
	if (uhi_cdc_dev.dev->speed == UHD_SPEED_HIGH) {
		if (line->sof == uhd_get_microframe_number()) {
			cpu_irq_restore(flags);
			return false;
		}
	} else {
		if (line->sof == uhd_get_frame_number()) {
			cpu_irq_restore(flags);
			return false;
		}
	}

	// Start transfer on empty buffer
	line->b_trans_ongoing = true;
	cpu_irq_restore(flags);

	return uhd_ep_run(
		uhi_cdc_dev.dev->address,
		line->ep_data,
		true,
		buf_nosel->ptr,
		line->buffer_size,
		10,
		uhi_cdc_rx_received);
}
Ejemplo n.º 5
0
static bool uhi_midi_rx_update(uhi_midi_line_t *line)
{
	irqflags_t flags;
	uhi_midi_buf_t *buf_nosel;
	uhi_midi_buf_t *buf_sel;

	flags = cpu_irq_save();
	// Check if transfer is already on-going
	if (line->b_trans_ongoing) 
	{
		cpu_irq_restore(flags);
		return false;
	}
	
	// Search a empty buffer to start a transfer

	//this makes local variables for the buffers that relate to sel and nosel
	buf_sel = &line->buffer[line->buf_sel];
	buf_nosel = &line->buffer[(line->buf_sel == 0)? 1 : 0];
	
	//if the position in the buffer has gone above or is equal to the number of bytes that were last transferred, reset the number of bytes transferred and the position to 0.
	if (buf_sel->pos >= buf_sel->nb) 
	{
		// The current buffer has been read
		// then reset it
		buf_sel->pos = 0;
		buf_sel->nb = 0;
		
	}
	
	//if the selected buffer is now empty and the other buffer has bytes to transfer, switch the selected and nonselected buffers, and assume there is new data to grab??
	if (!buf_sel->nb && buf_nosel->nb) 
	{
		// New data available then change current buffer
		line->buf_sel = (line->buf_sel == 0)? 1 : 0;
		buf_nosel = buf_sel;
		//LED_On(LED1);
		UHI_MIDI_RX_NOTIFY();

	}
	
	// if the nonselected buffer has stuff in it (but the currently selected buffer isn't empty!) then throw an error because there isn't an empty buffer available to start a transfer.
	if (buf_nosel->nb) 
	{
		// No empty buffer available to start a transfer
		cpu_irq_restore(flags);
		//LED_On(LED0);
		return false;
	}

	// Check if transfer must be delayed after the next SOF
	if (uhi_midi_dev.dev->speed == UHD_SPEED_HIGH) 
	{
		if (line->sof == uhd_get_microframe_number()) 
		{
			cpu_irq_restore(flags);
			return false;
		}
	} 
	else 
	{
		if (line->sof == uhd_get_frame_number()) 
		{
			cpu_irq_restore(flags);
			return false;
		}
	}

	// Start transfer on empty buffer

	// ok, either both buffers are empty, or there is an empty buffer that we just re-assigned as "nonselected". 
	// in this case, we are ready to set up an endpoint transfer into the empty buffer
	// let the system know that there is a transmission ongoing
	line->b_trans_ongoing = true;
	cpu_irq_restore(flags);
	
	//stupid test so that the LEDs show which buffer is selected
	/*
	if (line->buf_sel == 0)
	{
		LED_On(LED3);
	}
	else
	{
		LED_Off(LED3);
	}
	if (line->buf_sel == 1)
	{
		LED_On(LED2);
	}
	else
	{
		LED_Off(LED2);
	}
*/
	///  
	/// it appears that the ep run function gets data from the endpoint and puts it in the "nosel" buffer. Then it runs the rx_received function once this has finished.
	// there was at one point an issue, where if it times out then it thinks it has new data. I lengthened the timeout, and also made the rx_received function ignore data in the event of a timeout. JS
	return uhd_ep_run(
	uhi_midi_dev.dev->address,
	line->ep_data,
	true,
	buf_nosel->ptr,
	line->buffer_size,
	1000,
	uhi_midi_rx_received);
	//timeout was 10 originally
	

	
	/*
	//buf_sel = &line->buffer[0];
	//buf_nosel = &line->buffer[0];
	
	if (buf_sel->pos >= buf_sel->nb) {
		// The current buffer has been read
		// then reset it
		buf_sel->pos = 0;
		buf_sel->nb = 0;
		LED_On(LED0);
	}
	if (!buf_sel->nb && buf_nosel->nb) {
		// New data available then change current buffer
		line->buf_sel = (line->buf_sel == 0)? 1 : 0;
		//buf_nosel = buf_sel;
		LED_On(LED1);
	}					

	if (buf_nosel->nb) {
		// No empty buffer available to start a transfer
		cpu_irq_restore(flags);
		LED_On(LED3);
		return false;
	}
	
	if(buf_sel->nb)
	{
		cpu_irq_restore(flags);
		LED_On(LED3);
		return false;
	}

	// Check if transfer must be delayed after the next SOF
	if (uhi_midi_dev.dev->speed == UHD_SPEED_HIGH) {
		if (line->sof == uhd_get_microframe_number()) {
			cpu_irq_restore(flags);
			return false;
		}
	} else {
		if (line->sof == uhd_get_frame_number()) {
			cpu_irq_restore(flags);
			return false;
		}
	}

	// Start transfer on empty buffer
	line->b_trans_ongoing = true;
	cpu_irq_restore(flags);

	return uhd_ep_run(
	uhi_midi_dev.dev->address,
	line->ep_data,
	true,
	buf_nosel->ptr,
	line->buffer_size,
	10,
	uhi_midi_rx_received);
	*/
}