@@ -429,13 +429,17 @@ namespace klib::core::lpc17xx::io {
429429 }
430430 }
431431
432+ template <bool Isochronous>
432433 static void endpoint_out_callback (const uint8_t endpoint) {
433- // check if we are busy.
434- if (!state[endpoint].is_busy ) {
435- // set the flag we have a out interrupt pending
436- state[endpoint].interrupt_pending = true ;
437-
438- return ;
434+ // only check if we are busy if we are not a iso endpoint
435+ if constexpr (Isochronous) {
436+ // check if we are busy.
437+ if (!state[endpoint].is_busy ) {
438+ // set the flag we have a out interrupt pending
439+ state[endpoint].interrupt_pending = true ;
440+
441+ return ;
442+ }
439443 }
440444
441445 // receive more data
@@ -467,6 +471,50 @@ namespace klib::core::lpc17xx::io {
467471 }
468472 }
469473
474+ static void isochronous_irq_handler () {
475+ // we have a frame interrupt. Mark all the isochronous
476+ // endpoints as not busy
477+ for (uint32_t i = 0 ; i < (endpoint_count / 4 ); i++) {
478+ // get a iso endpoint
479+ const uint8_t ep = (i + 1 ) * 3 ;
480+
481+ // check if we are busy transmitting or receiving data
482+ if (!state[ep].is_busy ) {
483+ continue ;
484+ }
485+
486+ // get the current realized endpoints. If we allow
487+ // in and out on the same endpoint this wont work
488+ // but as we do not support that we can use this to
489+ // determine if we are a in or a out endpoint
490+ const uint32_t reep = (Usb::port->REEP >> (ep * 2 )) & 0x3 ;
491+
492+ // check what direction is enabled. We check for in
493+ // and out and if we do not have a match we call it
494+ // disabled
495+ const klib::usb::usb::endpoint_mode mode = (
496+ (reep == 0b01 ) ? klib::usb::usb::endpoint_mode::out : (
497+ (reep == 0b10 ) ? klib::usb::usb::endpoint_mode::in :
498+ klib::usb::usb::endpoint_mode::disabled
499+ )
500+ );
501+
502+ // check what to do based on the mode
503+ if (mode == klib::usb::usb::endpoint_mode::disabled) {
504+ // not something we can handle. Skip the endpoint
505+ continue ;
506+ }
507+
508+ // check how we need to handle the endpoint
509+ if (mode == klib::usb::usb::endpoint_mode::out) {
510+ endpoint_out_callback<true >(ep);
511+ }
512+ else {
513+ endpoint_in_callback (ep);
514+ }
515+ }
516+ }
517+
470518 static void data_irq_handler () {
471519 // get the endpoints we should handle
472520 uint32_t status = Usb::port->EPINTST ;
@@ -531,7 +579,7 @@ namespace klib::core::lpc17xx::io {
531579 endpoint_in_callback (ep);
532580 break ;
533581 case klib::usb::usb::endpoint_mode::out:
534- endpoint_out_callback (ep);
582+ endpoint_out_callback< false > (ep);
535583 break ;
536584 }
537585 }
@@ -626,10 +674,18 @@ namespace klib::core::lpc17xx::io {
626674 // we have a device status interrupt
627675 device_status_irq ();
628676 }
629- else if (masked_status & (0x1 << 2 )) {
677+
678+ // check for a endpoint interrupt
679+ if (masked_status & (0x1 << 2 )) {
630680 // we have a endpoint interrupt. Handle it in the data irq
631681 data_irq_handler ();
632682 }
683+
684+ // check for a frame interrupt
685+ if (masked_status & 0x1 ) {
686+ // we have a frame interrupt. Handle it in the iso irq
687+ isochronous_irq_handler ();
688+ }
633689 }
634690
635691 public:
@@ -814,6 +870,13 @@ namespace klib::core::lpc17xx::io {
814870 // clear the interrupt flag
815871 Usb::port->DEVINTCLR = 0x100 ;
816872
873+ // make sure the frame interrupt is enabled when a iso
874+ // endpoint is confiugred
875+ if (type == klib::usb::descriptor::transfer_type::isochronous) {
876+ // enable the frame interrupt
877+ Usb::port->DEVINTEN |= 0x1 ;
878+ }
879+
817880 // enable the endpoint
818881 write_command (command_phase::command,
819882 static_cast <uint8_t >(endpoint_command::select_endpoint) | ep, 0
0 commit comments