SENT sensor simulation

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
User19618
Level 1
Level 1
Hi,

I am working on a project, where a SENT sensor should be simulated. For that, the TC277 should behave as the Sensor and send a SENT signal to an ECU.
Any recommendations, how to do that with the TC277 in a good way? Might that also be possible with the SPC mode?

Best,
Chris
0 Likes
3 Replies
NeMa_4793301
Level 6
Level 6
10 likes received 10 solutions authored 5 solutions authored
Hmm, there's a very old application note AP32118 that had source code for a SENT simulator back in the TC17xx days. I'll see if I can dig it up.

That was before SPC was invented, so supporting SPC will be left as an exercise for the reader 😉
0 Likes
NeMa_4793301
Level 6
Level 6
10 likes received 10 solutions authored 5 solutions authored
I'm not sure it helps much, but here's the meat of the source code from way back in 2007. I'm only including the most important file: SENT_functions.c, because the rest of the source is more trouble than it's worth. The TC17xx peripherals were very different.

The CRC generation is easily salvageable: see function crc4 and the array CRC4Table. The rest of it works by setting up a PWM timer to correspond to each nibble in the SENT packet:
- CPU_viSRN0 is called to initiate transmission, and calculates the PWM timing for every nibble in the SENT message
- The timer ISR GPTA0_viSRN22 sets up the timing for subsequent nibbles and stops when it reaches the end.

I hope that helps a little. On the AURIX, you could set up a fancy DMA linked list that transmits a whole SENT packet without CPU intervention, or maybe even use the GTM's Multi-Channel Sequencer to control TOM outputs directly.

SPLIT INTO TWO POSTS due to 10000 character restriction


/*
============================================================================
== Infineon Technologies ==
== Disclaimer - Please Read ==
== ==
== No Warranty ==
== Because the program is licensed free of charge, there is no warranty ==
== for the program, to the extent permitted by applicable law. Except ==
== when otherwise stated in writing the copyright holders and/or other ==
== parties provide the program "as is" without warranty of any kind, ==
== either expressed or implied, including, but not limited to, the ==
== implied warranties of merchantability and fitness for a particular ==
== purpose. The entire risk as to the quality and performance of the ==
== program is with you. Should the program prove defective, you assume ==
== the cost of all necessary servicing, repair or correction. ==
== In no event unless required by applicable law or agreed to in writing ==
== will any copyright holder, or any other party who may modify and/or ==
== redistribute the program as permitted above, be liable to you for ==
== damages, including any general, special, incidental or consequential ==
== damages arising out of the use or inability to use the program ==
== (including but not limited to loss of data or data being rendered ==
== inaccurate or losses sustained by you or third parties or a failure ==
== of the program to operate with any other programs), even if such ==
== holder or other party has been advised of the possibility of such ==
== damages. ==
== End of disclaimer ==
============================================================================
*/


/*
----------------------------------------------------------------------------
Infineon Technologies AG
Copyright (c) 2007, All rights reserved

Project: SENT simulator
Revision: 1.2
Date: 08/11/2007


----------------------------------------------------------------------------
*/




#include "MAIN.h"

//****************************************************************************
// Global Variables
//****************************************************************************
//Debug
//ubyte volatile data_nibble_array[NUM_DATA_NIBBLE+1];
//ushort test_var1, test_var2;


extern volatile ushort *P_PERIOD_ARRAY;
extern volatile ushort *P_DUTY_ARRAY;
extern volatile ushort *P_PERIOD_NEXT_ARRAY;
extern volatile ushort *P_DUTY_NEXT_ARRAY;

extern volatile uword DATA;
extern volatile ushort SDATA;
extern volatile uword USER_DATA[USER_DATA_SIZE];
extern volatile ushort CLK_RATIO;
extern volatile ubyte CLK_DEV;
extern volatile ubyte ERROR_CODE;
extern volatile ubyte OP_MODE;


static volatile ubyte sent_toggle;
static volatile ubyte sent_nibble_count;
static volatile ushort *sent_p_period;
static volatile ushort *sent_p_duty;
static volatile ubyte udata_index;

#if SDATA_USED
static volatile ubyte sdata_nibble_index;
static volatile ubyte sent_sdata_nibble_array[16];
static volatile ubyte sent_sdata_nibble_array_next[16];
#endif

const ubyte CRC4Table[]=
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2,
7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8,
10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5,
14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1,
3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12,
9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6,
4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11,
1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14,
12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3,
6, 7, 4, 5, 2, 3, 0, 1, 14, 15, 12, 13, 10, 11, 8, 9,
11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13,
8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7,
5, 4, 7, 6, 1, 0, 3, 2, 13, 12, 15, 14, 9, 8, 11, 10
};

0 Likes
NeMa_4793301
Level 6
Level 6
10 likes received 10 solutions authored 5 solutions authored
PART 2 OF 2

/************************************************************************
* This function initilaizes the statics *
* *
*************************************************************************/

void init_sent_driver(void)

{
sent_toggle = 0;
sent_nibble_count=2;
sent_p_period = P_PERIOD_ARRAY;
sent_p_duty = P_DUTY_ARRAY;
udata_index=0;

#if SDATA_USED
calculate_sdata(SDATA, &sent_sdata_nibble_array);
calculate_sdata(SDATA, &sent_sdata_nibble_array_next);
#endif

GPTA0_LTCXR01 = *sent_p_period ;
GPTA0_LTCXR03 = *sent_p_duty;
GPTA0_EDCTR_G0EN = 1; // enable GPTA0 timer clock
}



/************************************************************************
* This interrupt function is called every time LTC00 resets *
* (indicates beginning of nibble) *
*************************************************************************/

void INTERRUPT (GPTA0_SRN22INT) GPTA0_viSRN22(void)
{
int i;

GPTA0_SRSC2 = 0x00000001; // reset LTC0 service request bit

if(sent_toggle==0)
{
GPTA0_LTCXR02 = *sent_p_period;
GPTA0_LTCXR04 = *sent_p_duty ;
sent_toggle = 1;
}
else
{
GPTA0_LTCXR01 = *sent_p_period ;
GPTA0_LTCXR03 = *sent_p_duty;
sent_toggle = 0;
}

GPTA0_LTCCTR00 = GPTA0_LTCCTR00 | 0x00000200;

if(sent_nibble_count == NUM_NIBBLE)
{
TOGGLEIO_P2_15;

sent_p_period = P_PERIOD_ARRAY;
sent_p_duty = P_DUTY_ARRAY;
sent_nibble_count = 1;




// Copy data to buffer
for(i=0; i {
*(sent_p_period + i) = *(P_PERIOD_NEXT_ARRAY + i);
*(sent_p_duty + i) = *(P_DUTY_NEXT_ARRAY + i);
}




//Trigger Next Frame processing.
CPU_SRC0 = CPU_SRC0 | 0x00008000;
}

else
{
sent_nibble_count++;
sent_p_period++;
sent_p_duty++;
}

}



/************************************************************************
* This interrupt function processes the next SENT Frame *
* *
*************************************************************************/

void INTERRUPT (CPU_SRN0INT) CPU_viSRN0(void)
{
ushort volatile *p_period, *p_duty;
ubyte volatile *p_data;
int i;
uword volatile sent_data;
ushort volatile sent_sdata;

ubyte volatile data_nibble_array[NUM_DATA_NIBBLE+1];
//MODIF
float volatile clock_ratio;
ubyte volatile op_mode;
ubyte volatile sdata_crc;




ENABLE();


p_period = P_PERIOD_NEXT_ARRAY;
p_duty = P_DUTY_NEXT_ARRAY;
p_data = (&data_nibble_array);
op_mode = OP_MODE;

#if SDATA_CRC
sdata_crc = 1;
#else
sdata_crc= 0;
#endif


if(op_mode==0)
sent_data = DATA;
else
sent_data = USER_DATA[udata_index];


//MODIF
clock_ratio= (((float)CLK_RATIO) * ((float)CLK_DEV) /((float)100));

#if SDATA_USED
sent_sdata=SDATA;
#endif

p_data = p_data+1-sdata_crc;

//*****program duty of all nibbles*****//
for(i=0; i< NUM_NIBBLE; i++)
{
*(p_duty+i) = 5 * clock_ratio;
}

//*****program period of cal pulse*****//
*p_period = (51 * clock_ratio)+ *p_duty;


//*****program period of serial nibble*****//
#if SDATA_USED
data_nibble_array[0]=sent_sdata_nibble_array[sdata_nibble_index];
#else
//-- all 0!
data_nibble_array[0]=0;
#endif
*(p_period+1) = ((data_nibble_array[0]+0x7) * clock_ratio)+ *(p_duty+1);


//*****compute data nibbles*****//:
for(i=0; i< NUM_DATA_NIBBLE; i++)
{
data_nibble_array[NUM_DATA_NIBBLE-i] = ((sent_data & (0xF << (4*i))) >> (4*i));
}

//*****program period of 2 x 3 data nibbles*****//.

for(i=0; i< NUM_DATA_NIBBLE ; i++)
{
*(p_period+2+i) = (data_nibble_array[i+1]+0x7)*clock_ratio + (*(p_duty+i+2));
}

//*****program period of CRC nibble*****//

*(p_period+NUM_DATA_NIBBLE+2) = (crc4(NUM_DATA_NIBBLE+sdata_crc, p_data)+0x7)*clock_ratio + (*(p_duty+NUM_DATA_NIBBLE+2));


//*****Handling of Index in User Table*****//
if(op_mode==1)
{
if(udata_index==USER_DATA_SIZE-1)
udata_index=0;
else
udata_index++;
}

//*****Handling of index in Serial Data Table*****//
//Maybe critical in terms of latency!!! The copying should be put in the GPTA SRN
#if SDATA_USED
if(sdata_nibble_index==0xf)
{
sdata_nibble_index=0;
for(i=0;i<=0xf;i++)
{
sent_sdata_nibble_array = sent_sdata_nibble_array_next;
}
calculate_sdata(sent_sdata, &sent_sdata_nibble_array_next);
}
else
sdata_nibble_index++;
#endif


//*****Handling of errors*****//
if(ERROR_CODE!=10)
{
switch(ERROR_CODE)
{
//+2% Clock drift
case(1):
CLK_DEV=CLK_DEV+2;
ERROR_CODE=0;
break;

//-2% Clock drift
case(2):
CLK_DEV=CLK_DEV-2;
ERROR_CODE=0;
break;

// Cal pulse as long as Data nibble 0xf
case(3):
*p_period = (22 * clock_ratio)+ *p_duty;
break;

// Last Data pulse as long Calibration pulse.
case(4):
*(p_period+NUM_DATA_NIBBLE+1) = *p_period;
break;

// Frame CRC erroneous
case(5):
*(p_period+NUM_DATA_NIBBLE+2) =(((~(crc4(NUM_DATA_NIBBLE+sdata_crc, p_data))) &0x0F)+0x7)*clock_ratio + (*(p_duty+NUM_DATA_NIBBLE+2));
break;

// Data Nibble 0 too short - CRC recalculated
case(6):
data_nibble_array[NUM_DATA_NIBBLE]=0x0;
*(p_period+NUM_DATA_NIBBLE+2) = (crc4(NUM_DATA_NIBBLE+sdata_crc, p_data)+0x7)*clock_ratio + (*(p_duty+NUM_DATA_NIBBLE+2));
*(p_period+NUM_DATA_NIBBLE+1)= 0x6*clock_ratio + (*(p_duty+NUM_DATA_NIBBLE+1));
break;

// Data Nibble 0 too long
case(7):
data_nibble_array[NUM_DATA_NIBBLE]=0xf;
*(p_period+NUM_DATA_NIBBLE+2) = (crc4(NUM_DATA_NIBBLE+sdata_crc, p_data)+0x7)*clock_ratio + (*(p_duty+NUM_DATA_NIBBLE+2));
*(p_period+NUM_DATA_NIBBLE+1)= 0x17*clock_ratio + (*(p_duty+NUM_DATA_NIBBLE+1));
break;

#if SDATA_USED
//Serial data bit missing:
case(8):
sent_sdata_nibble_array_next[0]= sent_sdata_nibble_array_next[0]&0x03;

///to kill
sent_sdata_nibble_array_next[12] = 0x0;
sent_sdata_nibble_array_next[13] = 0x0;
sent_sdata_nibble_array_next[14] = 0x0;
sent_sdata_nibble_array_next[15] = 0x0;
break;




//Serial data bit too early:
case(9):
sent_sdata_nibble_array_next[4]= sent_sdata_nibble_array_next[4]|0x04;
break;

//Serial data CRC error:
case(0):
sent_sdata_nibble_array_next[15]= ((~(sent_sdata_nibble_array_next[15]>>2))<<2)&0x04;
break;




#endif

}



#if (DEBUG==0)

ERROR_CODE=10;

#endif
}

}




/************************************************************************
* This function calculates the CRC4 checksum *
* (table look up implementation). *
*************************************************************************/
ubyte crc4(ubyte N, ubyte *p)

{

ubyte CheckSum, tempCS;
int i;
CheckSum=5;
for(i=0;i {
tempCS=(*(p+i)) +(CheckSum*16);
CheckSum = CRC4Table[tempCS];

//debug
// test_var1= tempCS;
// test_var2= CheckSum;

}
return(CheckSum);
}



/************************************************************************
* This function computes the serial data nibbles *
* *
*************************************************************************/
void calculate_sdata(ushort sdata, ubyte *p)

{
ubyte i, crc;
ubyte nibble_array[3];
ubyte *nibble;

nibble= &(nibble_array);
for(i=0x0; i<=11; i++)
{
*(p+i)=((sdata >> (11- i)) << 2) & 0x0004;
}

*p = (*p) | 0x08;

for(i=0; i<=2; i++)
{
*(nibble+i)= (sdata>> (8-4*i)) & 0x0f;
}
crc=crc4(3, nibble);

for(i=0x0; i<=3; i++)
{
*(p+12+i)= ((crc>>(3-i))<<2) & 0x04;
}
}



//end of file
0 Likes