예제 #1
0
dj_time_t dj_timer_getTimeMillis()
{
	return (dj_time_t)avr_millis();
}
예제 #2
0
int usb_dispatchPacket(uint8_t token, usb_endpoint * endpoint, unsigned int nakLimit)
{
	uint32_t timeout = avr_millis() + USB_XFER_TIMEOUT;
	uint8_t tmpdata;
	uint8_t rcode = 0;
	unsigned int nak_count = 0;
	char retry_count = 0;

	while (timeout > avr_millis())
	{
		// Analyze transfer result.

		// Launch the transfer.
		max3421e_write(MAX_REG_HXFR, (token | endpoint->address));
		rcode = 0xff;

		// Wait for interrupt
		while (timeout > avr_millis())
		{
			tmpdata = max3421e_read(MAX_REG_HIRQ);
			if (tmpdata & bmHXFRDNIRQ)
			{
				// Clear the interrupt.
				max3421e_write(MAX_REG_HIRQ, bmHXFRDNIRQ);

				rcode = 0x00;
				break;
			}
		}

		// Exit if timeout.
		if (rcode != 0x00)
			return (rcode);

		// Wait for HRSL
		while (timeout > avr_millis())
		{
			rcode = (max3421e_read(MAX_REG_HRSL) & 0x0f);
			if (rcode != hrBUSY)
				break;
//			else
//				avr_serialPrintf("busy!\n");
		}


		switch (rcode)
		{
			case hrNAK:
				nak_count++;
				if (nak_count == nakLimit)
					return (rcode);
				break;
			case hrTIMEOUT:
				retry_count++;
				if (retry_count == USB_RETRY_LIMIT)
					return (rcode);
				break;
			default:
				return (rcode);
		}
	}

	return (rcode);
}
예제 #3
0
/**
 * USB main task. Performs enumeration/cleanup
 */
void usb_poll(void)
{
	uint8_t i;
	uint8_t rcode;
	uint8_t tmpdata;
	static unsigned long delay = 0;
	usb_deviceDescriptor deviceDescriptor;

	// Poll the MAX3421E device.
	max3421e_poll();

	/* modify USB task state if Vbus changed */
	tmpdata = max3421e_getVbusState();

	switch (tmpdata)
	{
	case SE1: //illegal state
		usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
		break;
	case SE0: //disconnected
		if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
		{
			usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
		}
		break;
	case FSHOST: //attached
	case LSHOST:
		if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED)
		{
			delay = avr_millis() + USB_SETTLE_DELAY;
			usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
		}
		break;
	}// switch( tmpdata

	//Serial.print("USB task state: ");
	//Serial.println( usb_task_state, HEX );

	switch (usb_task_state)
	{
	case USB_DETACHED_SUBSTATE_INITIALIZE:

		// TODO right now it looks like the USB board is just reset on disconnect. Fire disconnect for all connected
		// devices.
		for (i = 1; i < USB_NUMDEVICES; i++)
			if (deviceTable[i].active)
				usb_fireEvent(&(deviceTable[i]), USB_DISCONNECT);

		usb_init();
		usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
		break;
	case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
		break;
	case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
		break;
	case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device
		if (delay < avr_millis())
		{
			usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
		}
		break;

	case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
		// Issue bus reset.
		max3421e_write(MAX_REG_HCTL, bmBUSRST);
		usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
		break;

	case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
		if ((max3421e_read(MAX_REG_HCTL) & bmBUSRST) == 0)
		{
			tmpdata = max3421e_read(MAX_REG_MODE) | bmSOFKAENAB; //start SOF generation
			max3421e_write(MAX_REG_MODE, tmpdata);
			//                  max3421e_regWr( rMODE, bmSOFKAENAB );
			usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
			delay = avr_millis() + 20; //20ms wait after reset per USB spec
		}
		break;

	case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
		if (max3421e_read(MAX_REG_HIRQ) & bmFRAMEIRQ)
		{ //when first SOF received we can continue
			if (delay < avr_millis())
			{ //20ms passed
				usb_task_state
						= USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
			}
		}
		break;

	case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE:
		// toggle( BPNT_0 );

		deviceTable[0].control.maxPacketSize = 8;

		rcode = usb_getDeviceDescriptor(&deviceTable[0], &deviceDescriptor);
		if (rcode == 0)
		{
			deviceTable[0].control.maxPacketSize = deviceDescriptor.bMaxPacketSize0;
			usb_task_state = USB_STATE_ADDRESSING;
		} else
		{
			usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
			usb_task_state = USB_STATE_ERROR;
		}
		break;

	case USB_STATE_ADDRESSING:

		// Look for an empty spot
		for (i = 1; i < USB_NUMDEVICES; i++)
		{
			if (!deviceTable[i].active)
			{
				// Set correct MaxPktSize
				// deviceTable[i].epinfo = deviceTable[0].epinfo;

				deviceTable[i].address = i;
				deviceTable[i].active = true;

				usb_initEndPoint(&(deviceTable[i].control), 0);

				//temporary record
				//until plugged with real device endpoint structure
				rcode = usb_setAddress(&deviceTable[0], i);

				if (rcode == 0)
				{
					usb_fireEvent(&deviceTable[i], USB_CONNECT);
					// usb_task_state = USB_STATE_CONFIGURING;
					// NB: I've bypassed the configuring state, because configuration should be handled
					// in the usb event handler.
					usb_task_state = USB_STATE_RUNNING;
				} else
				{
					usb_fireEvent(&deviceTable[i], USB_ADRESSING_ERROR);

					// TODO remove usb_error at some point?
					usb_error = USB_STATE_ADDRESSING;
					usb_task_state = USB_STATE_ERROR;
				}
				break; //break if address assigned or error occured during address assignment attempt
			}
		}

		// If no vacant spot was found in the device table, fire an error.
		if (usb_task_state == USB_STATE_ADDRESSING)
		{
			usb_fireEvent(&deviceTable[i], USB_ADRESSING_ERROR);

			// No vacant place in devtable
			usb_error = 0xfe;
			usb_task_state = USB_STATE_ERROR;
		}

		break;
	case USB_STATE_CONFIGURING:
		break;
	case USB_STATE_RUNNING:
		break;
	case USB_STATE_ERROR:
		break;
	}
}
예제 #4
0
/**
 * Performs ab out transfer to a USB device on an arbitrary endpoint.
 *
 * @param device USB bulk device.
 * @param device length number of bytes to read.
 * @param data target buffer.
 * @return number of bytes written, or error code in case of failure.
 */
int usb_write(usb_device * device, usb_endpoint * endpoint, uint16_t length, uint8_t * data)
{
	uint8_t rcode = 0, retry_count;

	// Set device address.
	max3421e_write(MAX_REG_PERADDR, device->address);

	// Local copy of the data pointer.
	uint8_t * data_p = data;

	unsigned int bytes_tosend, nak_count;
	unsigned int bytes_left = length;
	unsigned int nak_limit = USB_NAK_LIMIT;

	uint32_t timeout = avr_millis() + USB_XFER_TIMEOUT;

	uint8_t maxPacketSize = endpoint->maxPacketSize;

	// If maximum packet size is not set, return.
	if (!maxPacketSize) return 0xFE;

	max3421e_write(MAX_REG_HCTL, endpoint->sendToggle); //set toggle value

	while (bytes_left)
	{
		retry_count = 0;
		nak_count = 0;

		bytes_tosend = (bytes_left >= maxPacketSize) ? maxPacketSize : bytes_left;

		// Filling output FIFO
		max3421e_writeMultiple(MAX_REG_SNDFIFO, bytes_tosend, data_p);

		// Set number of bytes to send.
		max3421e_write(MAX_REG_SNDBC, bytes_tosend);

		// Dispatch packet.
		max3421e_write(MAX_REG_HXFR, (tokOUT | endpoint->address));

		// Wait for completion.
		while (!(max3421e_read(MAX_REG_HIRQ) & bmHXFRDNIRQ));

		// Clear IRQ.
		max3421e_write(MAX_REG_HIRQ, bmHXFRDNIRQ);

		rcode = (max3421e_read(MAX_REG_HRSL) & 0x0f);

		while (rcode && (timeout > avr_millis()))
		{
			switch (rcode)
			{
			case hrNAK:
				nak_count++;
				if (nak_limit && (nak_count == USB_NAK_LIMIT))
				{
					return (rcode); //return NAK
				}
				break;
			case hrTIMEOUT:
				retry_count++;
				if (retry_count == USB_RETRY_LIMIT)
				{
					return (rcode); //return TIMEOUT
				}
				break;
			default:
				return (rcode);
			}

			// Process NAK according to Host out NAK bug.
			max3421e_write(MAX_REG_SNDBC, 0);
			max3421e_write(MAX_REG_SNDFIFO, *data_p);
			max3421e_write(MAX_REG_SNDBC, bytes_tosend);
			max3421e_write(MAX_REG_HXFR, (tokOUT | endpoint->address)); //dispatch packet

			// Wait for the completion interrupt.
			while (!(max3421e_read(MAX_REG_HIRQ) & bmHXFRDNIRQ));

			// Clear interrupt.
			max3421e_write(MAX_REG_HIRQ, bmHXFRDNIRQ);

			rcode = (max3421e_read(MAX_REG_HRSL) & 0x0f);
		}

		bytes_left -= bytes_tosend;
		data_p += bytes_tosend;
	}

	endpoint->sendToggle = (max3421e_read(MAX_REG_HRSL) & bmSNDTOGRD) ? bmSNDTOG1 : bmSNDTOG0; //update toggle

	// Should be 0 in all cases.
	return (rcode);
}
예제 #5
0
/**
 *  @brief  get system's internal tick count in milliseconds.
 *          Used for time reference.
 *  @return current tick count.
 **/
unsigned long MLOSGetTickCount()
{
        return (long)avr_millis();
}