Bluetooth: controller: ISO resume ticker in ULL

Added function ull_conn_iso_resume_ticker_start to enable LLL ISO
peripheral/central to start the one-shot resume ticker.
At timeout the common lll_resume handler is called, and based on the
LLL state, the peripheral/central is able to resume the CIG event.

The resume acts exactly like a normal event resume from the prepare
pipeline, with the exception that the LLL must provide specific
lll_event instances.

Signed-off-by: Morten Priess <mtpr@oticon.com>
diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h
index 25feeb6..1352e93 100644
--- a/subsys/bluetooth/controller/ll_sw/lll.h
+++ b/subsys/bluetooth/controller/ll_sw/lll.h
@@ -113,6 +113,9 @@
 	TICKER_ID_CONN_ISO_BASE,
 	TICKER_ID_CONN_ISO_LAST = ((TICKER_ID_CONN_ISO_BASE) +
 				   (CONFIG_BT_CTLR_CONN_ISO_GROUPS) - 1),
+	TICKER_ID_CONN_ISO_RESUME_BASE,
+	TICKER_ID_CONN_ISO_RESUME_LAST = ((TICKER_ID_CONN_ISO_RESUME_BASE) +
+					  (CONFIG_BT_CTLR_CONN_ISO_GROUPS) - 1),
 #endif /* CONFIG_BT_CTLR_CONN_ISO */
 
 #if defined(CONFIG_BT_CTLR_USER_EXT) && \
diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h
index c95236b..7e2bbf0 100644
--- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h
+++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h
@@ -31,7 +31,6 @@
 	uint8_t  access_addr[4];    /* Access address */
 	uint32_t offset;            /* Offset of CIS from start of CIG in us */
 	uint32_t sub_interval;      /* Interval between subevents in us */
-	uint32_t subevent_length;   /* Length of subevent in us */
 	uint8_t  num_subevents;     /* Number of subevents */
 	struct lll_conn_iso_stream_rxtx rx; /* RX parameters */
 	struct lll_conn_iso_stream_rxtx tx; /* TX parameters */
@@ -57,16 +56,16 @@
 struct lll_conn_iso_group {
 	struct lll_hdr hdr;
 
-	uint16_t handle;   /* CIG handle (internal) */
-	uint8_t  num_cis;  /* Number of CISes in this CIG */
-	uint8_t  role;     /* 0: CENTRAL, 1: PERIPHERAL*/
+	uint16_t handle;        /* CIG handle (internal) */
+	uint8_t  num_cis : 5;   /* Number of CISes in this CIG */
+	uint8_t  role : 1;      /* 0: CENTRAL, 1: PERIPHERAL*/
+	uint8_t  paused : 1;    /* 1: CIG is paused */
 #if defined(CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP)
 	uint16_t cis_handles[CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP];
 #endif /* CONFIG_BT_CTLR_CONN_ISO_STREAMS */
 
 	/* Resumption information */
-	uint8_t  next_cis;  /* Next CIS to schedule */
-	uint32_t next_time; /* When to trigger next activity in the CIG */
+	uint8_t  resume_cis;    /* CIS index to schedule at resume */
 };
 
 int lll_conn_iso_init(void);
diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c
index f8e2e7f..d1086230 100644
--- a/subsys/bluetooth/controller/ll_sw/ull.c
+++ b/subsys/bluetooth/controller/ll_sw/ull.c
@@ -146,7 +146,10 @@
 
 #if defined(CONFIG_BT_CTLR_CONN_ISO)
 #define BT_CIG_TICKER_NODES ((TICKER_ID_CONN_ISO_LAST) - \
-			     (TICKER_ID_CONN_ISO_BASE) + 1)
+			     (TICKER_ID_CONN_ISO_BASE) + 1 + \
+			     (TICKER_ID_CONN_ISO_RESUME_LAST) - \
+			     (TICKER_ID_CONN_ISO_RESUME_BASE) + 1)
+
 #else
 #define BT_CIG_TICKER_NODES 0
 #endif
diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
index a7ebf12..4d2d5a4 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
+++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
@@ -11,12 +11,19 @@
 #include "util/memq.h"
 #include "util/mayfly.h"
 #include "ticker/ticker.h"
+#include "hal/ccm.h"
+#include "hal/ticker.h"
 
+#include "pdu.h"
 #include "lll.h"
+#include "lll_conn.h"
+#include "ull_conn_types.h"
 #include "lll_conn_iso.h"
 
 #include "ull_conn_iso_types.h"
+#include "ull_conn_internal.h"
 #include "ull_internal.h"
+#include "lll/lll_vendor.h"
 
 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
 #define LOG_MODULE_NAME bt_ctlr_ull_conn_iso
@@ -226,3 +233,94 @@
 			  ((void *)conn == ull_disable_mark_get()));
 	}
 }
+
+static void ticker_resume_op_cb(uint32_t status, void *param)
+{
+	ARG_UNUSED(param);
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+}
+
+static void ticker_resume_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			     uint16_t lazy, uint8_t force, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_resume};
+	struct lll_event *resume_event;
+	uint32_t ret;
+
+	LL_ASSERT(lazy == 0);
+
+	resume_event = param;
+
+	/* Append timing parameters */
+	resume_event->prepare_param.ticks_at_expire = ticks_at_expire;
+	resume_event->prepare_param.remainder = remainder;
+	resume_event->prepare_param.lazy = 0;
+	resume_event->prepare_param.force = force;
+	mfy.param = resume_event;
+
+	/* Kick LLL resume */
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+			     0, &mfy);
+
+	LL_ASSERT(!ret);
+}
+
+void ull_conn_iso_resume_ticker_start(struct lll_event *resume_event,
+				      uint8_t  resume_cis_index,
+				      uint32_t ticks_anchor,
+				      uint32_t resume_timeout)
+{
+	struct lll_conn_iso_group *cig;
+	uint32_t ready_delay_us;
+	uint32_t resume_delay_us;
+	int32_t resume_offset_us;
+	uint8_t ticker_id;
+	uint32_t ret;
+
+	cig = resume_event->prepare_param.param;
+	ticker_id = TICKER_ID_CONN_ISO_RESUME_BASE + cig->handle;
+
+	cig->resume_cis = resume_cis_index;
+
+	if (0) {
+#if defined(CONFIG_BT_CTLR_PHY)
+	} else {
+		struct ll_conn_iso_stream *cis;
+		struct ll_conn *acl;
+
+		cis = ll_conn_iso_stream_get(cig->cis_handles[resume_cis_index]);
+		acl = ll_conn_get(cis->lll.acl_handle);
+
+		ready_delay_us = lll_radio_rx_ready_delay_get(acl->lll.phy_rx, 1);
+#else
+	} else {
+		ready_delay_us = lll_radio_rx_ready_delay_get(0, 0);
+#endif /* CONFIG_BT_CTLR_PHY */
+	}
+
+	resume_delay_us  = EVENT_OVERHEAD_START_US;
+	resume_delay_us += EVENT_TICKER_RES_MARGIN_US;
+	resume_delay_us += EVENT_JITTER_US;
+	resume_delay_us += ready_delay_us;
+
+	resume_offset_us = (int32_t)(resume_timeout - resume_delay_us);
+	LL_ASSERT(resume_offset_us >= 0);
+
+	/* Setup resume timeout as single-shot */
+	ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+			   TICKER_USER_ID_LLL,
+			   ticker_id,
+			   ticks_anchor,
+			   HAL_TICKER_US_TO_TICKS(resume_offset_us),
+			   TICKER_NULL_PERIOD,
+			   TICKER_NULL_REMAINDER,
+			   TICKER_NULL_LAZY,
+			   TICKER_NULL_SLOT,
+			   ticker_resume_cb, resume_event,
+			   ticker_resume_op_cb, NULL);
+
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h
index 0f7557c..bb73ce5 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h
+++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h
@@ -22,3 +22,8 @@
 
 void ull_conn_iso_done(struct node_rx_event_done *done);
 void ull_conn_iso_cis_established(struct ll_conn_iso_stream *cis);
+
+void ull_conn_iso_resume_ticker_start(struct lll_event *resume_event,
+				      uint8_t  resume_cis,
+				      uint32_t ticks_anchor,
+				      uint32_t resume_timeout);