dj_time_t dj_timer_getTimeMillis() { return (dj_time_t)avr_millis(); }
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); }
/** * 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; } }
/** * 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); }
/** * @brief get system's internal tick count in milliseconds. * Used for time reference. * @return current tick count. **/ unsigned long MLOSGetTickCount() { return (long)avr_millis(); }