How to use reference Address mode to achieve different phase output of two QOM channels for MPC5554

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to use reference Address mode to achieve different phase output of two QOM channels for MPC5554

370 Views
xieyuzhuo
Contributor I

Hello,My ultimate goal is to achieve three QOM channels output the same waveform, but with a fixed time difference.

I use the QOM function of MPC5554 to control the output waveform of QOM by assigning the address of the event array stored in QOM directly. Qom0 and QOM1 channels use reference mode, QOM2 channel uses immediate mode. I assign ref directly to the following address:

ref=(uint32_t *) ((uint32_t) fs_etpu_data_ram (QOM2_CHANNEL) - (uint32_t) & ETPU_DATA_RAM + FS_ETPU_QOM_LAST_MATCH_TIME_OFFSET);

*(pba + ((FS_ETPU_QOM_REF_ADDR_PTR_OFFSET - 1)>> 2)) = (uint24_t) ref;

But when I use the Reference Address mode, QOM0 and QOM1 do not start with the last match of Qom2 and the time difference of QOM0 and QOM1 between QOM2 is random. Is the reference Address pattern used to assign values directly to the ref's address? How to use reference Address schema correctly?

static uint8_t Event_Array_Update(uint8_t channel,uint32_t CTL_Array[],uint8_t CTL_Array_size) 
{
uint32_t *pba;
uint32_t *pba_array;
uint8_t i;
if (eTPU->CHAN[channel].CR.B.CPBA != 0)
{
pba = fs_etpu_data_ram (channel);
pba_array = (pba + (FS_ETPU_QOM_NUM_PARMS) / 4);
}
else return 1;

for(i=0;i<CTL_Array_size;i++) 
{
if (i%2==0)
{
*(pba_array + i) = (CTL_Array[i] << 1) + 1;
}
else
{
*(pba_array + i) = (CTL_Array[i] << 1) + 0;
}
}
}

static uint8_t fs_etpu_qom_loop_update(uint8_t QOM_channel,uint8_t loop,uint8_t IC_channel,uint32_t * ref) 
{
//only used to FS_ETPU_QOM_LOOP mode channel
uint32_t *pba;
uint8_t *pba8;
uint8_t i;

if (eTPU->CHAN[QOM_channel].CR.B.CPBA != 0)
{
pba = fs_etpu_data_ram (QOM_channel); 
pba8 = (uint8_t *) pba;
/*only write reference pointer if using that mode. */
*(pba + ((FS_ETPU_QOM_REF_ADDR_PTR_OFFSET - 1) >> 2)) = (uint24_t) ref;
}
else return 1;

if (mapTestMode == 0)
{
*(pba8 + FS_ETPU_QOM_LOOP_COUNT_OFFSET) = loop;
eTPU->CHAN[IC_channel].CR.B.CIE = TRUE;
eTPU->CHAN[QOM_channel].SCR.R = FS_ETPU_QOM_LOOP;
}
else if (mapTestMode == 1)
{
eTPU->CHAN[IC_channel].CR.B.CIE = FALSE;
eTPU->CHAN[QOM_channel].SCR.R = FS_ETPU_QOM_CONTINUOUS;
}

eTPU->CHAN[QOM_channel].HSRR.R = FS_ETPU_QOM_INIT_PIN_LOW;
eTPU->CHAN[QOM_channel].CR.R =
(FS_ETPU_PRIORITY_MIDDLE << 28) + (FS_ETPU_QOM_TABLE_SELECT << 24) +
(FS_ETPU_QOM_FUNCTION_NUMBER << 16) + (((uint32_t)pba -
fs_etpu_data_ram_start) >> 3);

}

void Data_Update_all(void)
{
{
CTL_off_Time_Map=check_bound24(CTL_off_Time_Map,4000000,0); 
CTL_1st_oil_Map=check_bound16(CTL_1st_oil_Map,2500,0);
CTL_1to2_oil_off_Time_Map=check_bound24(CTL_1to2_oil_off_Time_Map,4000000,0);
CTL_2nd_oil_Map=check_bound16(CTL_2nd_oil_Map,2500,0);
CTL_2to3_oil_off_Time_Map=check_bound24(CTL_2to3_oil_off_Time_Map,4000000,0);
CTL_3rd_oil_Map=check_bound16(CTL_3rd_oil_Map,2500,0);

INJE1[0]=CTL_off_Time_Map;
INJE1[1]=CTL_1st_oil_Map;
INJE1[2]=CTL_1to2_oil_off_Time_Map;
INJE1[3]=CTL_2nd_oil_Map;
INJE1[4]=CTL_2to3_oil_off_Time_Map;
INJE1[5]=CTL_3rd_oil_Map;
ref1=(uint32_t *) ((uint32_t) fs_etpu_data_ram (QOM2_CHANNEL) - (uint32_t) & ETPU_DATA_RAM + FS_ETPU_QOM_LAST_MATCH_TIME_OFFSET);
//ref1=(uint32_t *) 0x00023420;
Event_Array_Update(QOM0_CHANNEL,INJE1,6);

INJE2[0]=CTL_off_Time_Map;
INJE2[1]=CTL_1st_oil_Map;
INJE2[2]=CTL_1to2_oil_off_Time_Map;
INJE2[3]=CTL_2nd_oil_Map;
INJE2[4]=CTL_2to3_oil_off_Time_Map;
INJE2[5]=CTL_3rd_oil_Map;
ref2=(uint32_t *) ((uint32_t) fs_etpu_data_ram (QOM2_CHANNEL) - (uint32_t) & ETPU_DATA_RAM + FS_ETPU_QOM_LAST_MATCH_TIME_OFFSET);
Event_Array_Update(QOM1_CHANNEL,INJE2,6);

INJE3[0]=CTL_off_Time_Map;
INJE3[1]=CTL_1st_oil_Map;
INJE3[2]=CTL_1to2_oil_off_Time_Map;
INJE3[3]=CTL_2nd_oil_Map;
INJE3[4]=CTL_2to3_oil_off_Time_Map;
INJE3[5]=CTL_3rd_oil_Map;
ref3=0;
Event_Array_Update(QOM2_CHANNEL,INJE3,6);

}

}

Tags (1)
0 Kudos
1 Reply

357 Views
johndiener
Contributor IV

I think it would be hard to get the output you desire by having one QOM channel run immediate first match mode and then having the other 2 channels reference off the last match time of that "master" channel. For one, the last match time is not set within a QOM channel until the first match in the set has completed (after offset 1), so unless the timing was just right, the reference value used would not be as expected.
It depends somewhat on how large the time difference needs to be between the 3 channel output waveforms, and how close your timing is to overflowing 23 bits, but I'd be more inclined to do something like this:
- allocate 3 words of eTPU data RAM to serve as a reference for each of the 3 channels
- write the timebase (current TCR1 or TCR2 register value) to the first reference data location, and then add the time difference for the remaining 2 waveforms to this first reference value and write the results into the 2nd and 3rd reference locations
- configure all 3 QOM channels to use reference first match mode and point them at these 3 different reference values
There are other considerations of course - are you running single shot, continuous or loop mode? Assuming you want to modify the waveform offsets at times, how does that need to be managed? Could <fixed time difference> + offset1 be greater than 0x800000 counter units? Anyways, somewhat complex to wok through, but I believe a solution could be achieved.

John Diener