Bluetooth: controller: CIS Central fixes

- New calculation of Max_PDU for framed case according to BT Core 5.4
- Fix CIS_Offset calculation for multiple CIS usecase
- Fix resume ticker setup for central

Signed-off-by: Morten Priess <mtpr@oticon.com>
diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c
index e601673..172bc28 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c
+++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c
@@ -44,6 +44,8 @@
 
 #include "hal/debug.h"
 
+#define SDU_MAX_DRIFT_PPM 100
+
 /* Setup cache for CIG commit transaction */
 static struct {
 	struct ll_conn_iso_group group;
@@ -167,6 +169,44 @@
 	return BT_HCI_ERR_SUCCESS;
 }
 
+static void set_bn_max_pdu(bool framed, uint32_t iso_interval, uint32_t sdu_interval,
+			   uint16_t max_sdu, uint8_t *bn, uint8_t *max_pdu)
+{
+	uint32_t ceil_f_x_max_sdu;
+	uint16_t max_pdu_bn1;
+	uint32_t max_drift;
+	uint32_t ceil_f;
+
+	if (framed) {
+		/* Framed (From ES-18002):
+		 *   Max_PDU >= ((ceil(F) x 5 + ceil(F x Max_SDU)) / BN) + 2
+		 *   F = (1 + MaxDrift) x ISO_Interval / SDU_Interval
+		 *   SegmentationHeader + TimeOffset = 5 bytes
+		 *   Continuation header = 2 bytes
+		 *   MaxDrift (Max. allowed SDU delivery timing drift) = 100 ppm
+		 */
+		max_drift = ceiling_fraction(SDU_MAX_DRIFT_PPM * sdu_interval, 1000000U);
+		ceil_f = ceiling_fraction(iso_interval + max_drift, sdu_interval);
+		ceil_f_x_max_sdu = ceiling_fraction(max_sdu * (iso_interval + max_drift),
+						    sdu_interval);
+
+		/* Strategy: Keep lowest possible BN.
+		 * TODO: Implement other strategies, possibly as policies.
+		 */
+		max_pdu_bn1 = ceil_f * 5 + ceil_f_x_max_sdu;
+		*bn = ceiling_fraction(max_pdu_bn1, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE);
+		*max_pdu = ceiling_fraction(max_pdu_bn1, *bn) + 2;
+	} else {
+		/* For unframed, ISO_Interval must be N x SDU_Interval */
+		LL_ASSERT(iso_interval % sdu_interval == 0);
+
+		/* Core 5.3 Vol 6, Part G section 2.1:
+		 * BN >= ceil(Max_SDU/Max_PDU * ISO_Interval/SDU_Interval)
+		 */
+		*bn = ceiling_fraction(max_sdu * iso_interval, (*max_pdu) * sdu_interval);
+	}
+}
+
 
 /* TODO:
  * - Drop retransmissions to stay within Max_Transmission_Latency instead of asserting
@@ -278,30 +318,29 @@
 			tx = cig->c_sdu_interval && cis->c_max_sdu;
 			rx = cig->p_sdu_interval && cis->p_max_sdu;
 
-			if (cis->framed) {
-				cis->lll.tx.max_octets =
-					ceiling_fraction(cis->c_max_sdu * cig->c_sdu_interval,
-							 iso_interval_us);
-				cis->lll.rx.max_octets =
-					ceiling_fraction(cis->p_max_sdu * cig->c_sdu_interval,
-							 iso_interval_us);
-			} else {
-				/* For unframed, ISO_Interval must be N x SDU_Interval */
-				LL_ASSERT(iso_interval_us % cig->c_sdu_interval == 0);
+			/* Use Max_PDU = MIN(<buffer_size>, Max_SDU) as default. May be changed by
+			 * set_bn_max_pdu.
+			 */
+			cis->lll.tx.max_octets = MIN(CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE,
+						     cis->c_max_sdu);
+			cis->lll.rx.max_octets = MIN(251, cis->p_max_sdu);
 
-				/* Use Max_PDU = MIN(<buffer_size>, Max_SDU) */
-				cis->lll.tx.max_octets = MIN(CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE,
-							 cis->c_max_sdu);
-				cis->lll.rx.max_octets = MIN(251, cis->p_max_sdu);
+			/* Calculate BN and Max_PDU (framed) for both directions */
+			if (tx) {
+				set_bn_max_pdu(cis->framed, iso_interval_us, cig->c_sdu_interval,
+					       cis->c_max_sdu, &cis->lll.tx.burst_number,
+					       &cis->lll.tx.max_octets);
+			} else {
+				cis->lll.tx.burst_number = 0;
 			}
 
-			/* BN >= Max_SDU/Max_PDU * ISO_Interval/SDU_Interval */
-			cis->lll.tx.burst_number = tx ?
-				ceiling_fraction(cis->c_max_sdu * iso_interval_us,
-						 cis->lll.tx.max_octets * cig->c_sdu_interval) : 0;
-			cis->lll.rx.burst_number = rx ?
-				ceiling_fraction(cis->p_max_sdu * iso_interval_us,
-						 cis->lll.rx.max_octets * cig->p_sdu_interval) : 0;
+			if (rx) {
+				set_bn_max_pdu(cis->framed, iso_interval_us, cig->p_sdu_interval,
+					       cis->p_max_sdu, &cis->lll.rx.burst_number,
+					       &cis->lll.rx.max_octets);
+			} else {
+				cis->lll.rx.burst_number = 0;
+			}
 		}
 
 		/* Calculate SE_Length */
@@ -621,7 +660,6 @@
 		int16_t conn_events_since_ref;
 		uint32_t iso_interval_us;
 		uint32_t time_since_ref;
-		uint32_t acl_offset;
 
 		c = ll_conn_iso_stream_get_by_group(cig, &handle_iter);
 		if (c->cis_id != cis->cis_id && c->lll.active) {
@@ -630,9 +668,8 @@
 
 			time_since_ref = c->offset + conn_events_since_ref * conn->lll.interval *
 					 CONN_INT_UNIT_US;
-			iso_interval_us = cig->iso_interval * CONN_INT_UNIT_US;
-			acl_offset = iso_interval_us - (time_since_ref % iso_interval_us);
-			cis_offset = acl_offset + (cig->sync_delay - cis->sync_delay);
+			iso_interval_us = cig->iso_interval * ISO_INT_UNIT_US;
+			cis_offset = time_since_ref % iso_interval_us;
 			break;
 		}
 	}
diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
index 5bdbd39..00b60e5 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
+++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
@@ -442,7 +442,6 @@
 				      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;
@@ -458,26 +457,28 @@
 	}
 	cig->resume_cis = cis_handle;
 
-	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(cis_handle);
-		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;
+
+	if (cig->role == BT_HCI_ROLE_PERIPHERAL) {
+		/* Add peripheral specific delay */
+		resume_delay_us += EVENT_JITTER_US;
+		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(cis_handle);
+			acl = ll_conn_get(cis->lll.acl_handle);
+
+			resume_delay_us += lll_radio_rx_ready_delay_get(acl->lll.phy_rx, 1);
+#else
+		} else {
+			resume_delay_us += lll_radio_rx_ready_delay_get(0, 0);
+#endif /* CONFIG_BT_CTLR_PHY */
+		}
+	}
 
 	resume_offset_us = (int32_t)(resume_timeout - resume_delay_us);
 	LL_ASSERT(resume_offset_us >= 0);
@@ -631,8 +632,7 @@
 #elif !defined(CONFIG_BT_CTLR_CENTRAL_ISO)
 	mfy.fp = lll_peripheral_iso_prepare;
 #else
-	mfy.fp = (cig->lll.role == BT_HCI_ROLE_PERIPHERAL) ? lll_peripheral_iso_prepare :
-							     lll_central_iso_prepare;
+	mfy.fp = IS_PERIPHERAL(cig) ? lll_peripheral_iso_prepare : lll_central_iso_prepare;
 #endif
 
 	if (IS_PERIPHERAL(cig) && cig->sca_update) {