The static PRACH scheduling mechanism allows a recurring PRACH capture to be specified for a given channel. It is based around the ORAN time domain configuration of the PRACH from O-RAN.WG4.MP.0-v6.00, section 12.6.1.
The API requires the following information to be provided when scheduling static PRACH captures:
- The period after which the capture repeats, measured in radio frames. This can be from 1 to 256 frames.
- The frame number within the repeating period within which the PRACH capture should occur. Each period is indexed starting from frame 0. This value can be from 0 to 255 and must always be less than the value specified for the period length.
- The subframe number at which the PRACH capture should begin. Subframes are numbered from 0 to 9.
- The slot number at which the PRACH capture should begin. When the CC has a 15 kHz sub-carrier spacing, the slot duration is equal to the subframe duration and this number should be set to 0. When a 30 kHz SCS is used, there are two slots per subframe and this number may therefore be set to 0 or 1. For 60 kHz the range is 0-3 and for 120 kHz the range is 0-7.
- The duration of the PRACH capture, measured in slots. This includes the duration of the cyclic prefix and the guard period.
- The number of repeats of the PRACH transmission that should be captured consecutively. In this context a repeat of the PRACH transmission consists of the CP, one or more PRACH sequences and the guard period.
The starting point (frame, subframe, and slot) and run length (duration, repeats) must be chosen such that the PRACH capture's total length is less than the pattern period.
See XDfePrach_Schedule for details of the API data structure used to represent a PRACH static schedule.
The API provides functions to set up the static schedule for a RACH channel and trigger it to take effect based on a timing synchronization point aligned with a chosen bit of the TUSER bus. This is illustrated by the following example code.
/* Declare and populate trigger and RACH capture configuration */
XDfePrach_CCCfg CCCfg; //CC Config structure
XDfePrach_RCCfg RCCfg; //RC Config structure
XDfePrach_TriggerCfg TriggerCfg;
XDfePrach_DDCCfg DdcCfg = { 0 };
XDfePrach_NCOCfg NcoCfg = { 0 };
XDfePrach_Schedule SchedCfg = { 0 };
XDfePrach_StatusMask status = { 0 };
u32 BitSequence;
u32 CCID;
u32 RCId;
u32 result;
CCID = 0; // CCID on which to perform RACH extraction
RCId = 0; // RACH channel identifier (0-15)
//Single Shot RACH update trigger on Band0(always band 0), TUSER bit 0
TriggerCfg.RachUpdate.Mode = 1; // Single-shot trigger
TriggerCfg.RachUpdate.TUSERBit = 0; // on bit 0
TriggerCfg.RachUpdate.TuserEdgeLevel = 1; // when high
//Single-Shot Frame Init on band 0, TUSER bit 3
TriggerCfg.FrameInit[0].TUSERBit=3;
TriggerCfg.FrameInit[0].TuserEdgeLevel =3;
TriggerCfg.FrameInit[0].Mode =1;
/* Set up NcoCfg */
NcoCfg.Frequency = 32;
NcoCfg.NcoGain = 1;
/* Set up DdcCfg - default RachGain is 0dB for all stages */
DdcCfg.DecimationRate = 2; // Rate #2 = 4x decimation
DdcCfg.SCS = 1; // SCS #1 = 30 kHz spacing
/* Set up SchedCfg */
SchedCfg.PatternPeriod = 10; // Enable every tenth frame
SchedCfg.FrameID = 1; // Start on second frame of the period
SchedCfg.SubframeID = 0; // Start on first subframe
SchedCfg.SlotId = 0; // Start on first slot
SchedCfg.Duration = 8; // Number of slots to capture
SchedCfg.Repeats = 2; // Perform two consecutive captures
/* Clear the RACH update and frame init event status */
status.RachUpdate = 1;
status.FrameInit[0] = 1;
XDfePrach_ClearEventStatus(InstancePtr, &status);
/* Get the existing CC and RC configuration from the core*/
XDfePrach_GetCurrentCCCfg(InstancePtr, &CCCfg);
XDfePrach_GetCurrentRCCfg(InstancePtr,&RCCfg);
/* Add the new RACH channel(RCID=0) to the RCCfg(assumes CCID==0 already configured on band 0)*/
result = XDfePrach_AddRCtoRCCfgMB(InstancePtr, &RCCfg, CCID, RCID,RCID,&DdcCfg, &NcoCfg, &SchedCfg,0);
if (result != XST_SUCCESS)
printf("Add RCId #%d failed with error code %d!\n", RCId, result);
/* sent the updated configs back to the core */
result = XDfePrach_SetNextCfg(InstancePtr, &CCCfg, &RCCfg);
if (result != XST_SUCCESS)
printf("XDfePrach_SetNextCfg failed with error code %d!\n", result);
else
{
printf("Successfully scheduled RCId #%d for addition.\n", RCId);
status.RachUpdate = 0;
status.FrameInit[0] = 0;
/* (Demonstration only!) Poll for successful RACH update trigger */
while (status.RachUpdate == 0 && status.FrameInit[0] = 0)
{
XDfePrach_GetEventStatus(InstancePtr, &status);
usleep(10000);
}
printf("Addition of RCId #%d was triggered successfully.\n", RCId);
}
The polling loop at the end of this example is not realistic, but illustrates
how the API can determine whether the RACH update trigger condition and the FrameInit
trigger condition have occurred. In order to
correctly load the CC configuration and RACH channel configuration, the RACH update
trigger condition must be satisfied to tell the core that the new configurations are
available and then the FrameInit
trigger condition
must be satisfied to align the scheduler and initiate the PRACH capture.
Adding multiple RACH channels can be performed by making multiple calls to
XDfePrach_AddRCtoRCCfgMB
before calling XDfePrach_SetNextCfg
. Updates to the component carrier
configuration can also be made by calling XDfePrach_AddCCtoCCCfgMB
one or more times before calling XDfePrach_AddRCtoRCCfgMB
.
SchedCfg
added in the above example, will
create a pattern of captures which repeats after 10 frames. It will begin capturing on
the first slot of the first subframe of the second frame in the repeat of 10 frames. The
capture will last for 27 slots, this will be structured as three (num_repeats+1) blocks
of samples, each delineated by TLAST. Each block of samples will last for nine slots
(Duration +1). The number of samples per block will depend upon the input CC sample
rate, the CC SCS value, which determines the length of a slot, and the decimation rate
applied in the DFE PRACH core.