This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

N2HET unexpected behavior

I am running the following code found in one of the application notes to generate a sine wave PWM with the N2HET.

L00: CNT{next=L01, reqnum=0, request=GENREQ, reg=A, irq=OFF, max=PWM_PERIOD}; 
L01: ECMP{next=L03, hr_lr=HIGH, en_pin_action=ON, cond_addr=L02, pin=PWM_PIN_NUM, action=PULSELO, reg=A, irq=OFF, data=INIT_COMPARE, hr_data=INIT_HR_DELAY}; 
L02: MOV32 { remote=L01,type=IMTOREG&REM,reg=NONE,data=INIT_COMPARE,hr_data=INIT_HR_DELAY}; 
L03: BR{next=L00, cond_addr=L00, event=NOCOND}


However, the behavior I see is not what I understand from the TRM. I reckon the CNT instruction counts up to max_count and then resets the data field, while modifying the A register. The ECMP instruction compares the A register with its data field and PULSES the pin 0. So essentially the PWM period is determined by the max_count in the CNT instruction and the duty cycle (in terms of counts) is determined by the data field in the ECMP instruction.

But when I give the values of say, PERIOD = 100, and PULSE_WIDTH = 50 to max_count and data in the CNT and ECMP instructions respectively, I get a very slim spike on the pin. granted I can vary its width but not to the full extent of the PERIOD.

To get the behavior that I want, I have to do something more along these lines.
PERIOD = 100
PULSE_WIDTH = 50 * 50

Or something like that.

Am I not understanding the documentation correctly and this is the intended behavior? Or am I doing something wrong in the configuration?

Host side code as follows:

#include <math.h>
#include <stdint.h>
#include <stdbool.h>

#include "sys_common.h"
#include "het.h"
#include "htu.h"
#include "Sine_wave.h"

#define SINE_FREQ_DIVIDER 	16
#define LRPFC			7
#define NHET1_PWM_PIN		PIN_HET_0
#define CNT_MAX_PERIOD 		SINE_FREQ_DIVIDER
#define SAMPLE_SIZE		128
#define PI			3.14159f

float sine_table [SAMPLE_SIZE] = {};
uint32_t sine_digital_table [SAMPLE_SIZE] = {};


void htuInit(void)
{
	htuRAM1->DCP[0].ITCOUNT = 0x00010000 + SAMPLE_SIZE;
	htuRAM1->DCP[0].IHADDRCT = (htuRAM1->DCP[0].IHADDRCT & 0x0) | //Clear Register
								0x1 << 23 |		//DIR
								0x0 << 22 |		//SIZE
								0x0 << 21 |		//ADDMH
								0x0 << 20 |		//ADDFM
								0x1 << 18 |		//TMBA
								0x0 << 16 |		//TMBB
								0x28;			//IHADDR
	htuRAM1->DCP[0].IFADDRA = (unsigned int)sine_digital_table;

	htuREG1->CPENA = 0x00000001;
	htuREG1->GC = 0x00010000;
}

void configNHET1()
{
	hetREG1->PFR = LRPFC << 8;
	hetREG1->REQENS = 1;
	hetREG1->DIR = (1 << NHET1_PWM_PIN);
	hetRAM1->Instruction[pHET_L00_0].Control = (uint32_t)(SAMPLE_SIZE) |
			(hetRAM1->Instruction[pHET_L00_0].Control & 0xFE000000);
	hetRAM1->Instruction[pHET_L01_0].Control =
			(hetRAM1->Instruction[pHET_L01_0].Control & 0xFFFFE0FF) |
			(NHET1_PWM_PIN << 8);
}

void main(void)
{
	//C-style variable declaration
	uint16_t iter_sine;

	//Initialization Code
	for ( iter_sine = 0; iter_sine < SAMPLE_SIZE; iter_sine++ ) {
		sine_table[iter_sine] = sinf(2.0f * PI * ((float)iter_sine) / ((float)SAMPLE_SIZE)) * 0.5f + 0.5f;
		sine_digital_table[iter_sine] = sine_table[iter_sine] * ((float)(SAMPLE_SIZE * SAMPLE_SIZE));
	}

	htuInit();
	hetInit();
	configNHET1();

	while(1);
}
  • Safiullah,

    You've got the idea of the CNT instruction. But it executes once per HET loop resolution period.

    Where exactly does the 'period' value go? The reason I ask is that a period of 100 might be less than a loop resolution period and in that case the code won't work. You need it to be able to execute the CNT instruction at least twice if you think about it. It has to execute once and trigger ECMP to take the pin action, and again to take the opposite action.

    So the fastest you can toggle is 2 LRP. Your LRP value is set by the PCF register (prescale factor) bits 10:8.

    Depending on how you have this set, and where the value of 100 goes - this may be the problem.

    First, the values of PFR.LRPFC set the divider in powers of 2, so 7 = /128, 6 = /64, 5=/32 etc.

    Let's assume you set PFR.LRPFC to 7 = /128. Then it takes 256 clocks to execute 2 HET loops.

    If the value 100 is the 'hi-res' value - meaning it gets written to the hr_data field of the instruction, then it would be 100 clocks. And so you would be trying to run the HET about 2.5 times faster than it can run in this particular combination.

    Now the program isn't very big, so you could reduce the LRP to something like 5=32 and it would probably run without overflow. In that case 2 loops would be 64 clocks, so a period of 100 would be OK.

    If the 100 is going into the data= field and not the hr_data=field - then its something else not this ... because the data field is in units of loop resolution periods. So data=100 would mean the CNT instruction could execute about 100 times during that period and it would have to be a different issue.

    Since you got something to work when you put in 2500 (50*50) though - LRP and the actual value (units) of PERIOD are the first things' I'd check.

    -Anthony
  • So the way I understand it, (I could be off course here) is that that my instructions should complete within one high resolution cycle. If that is that case then with HET1PFR register's LR field is loaded with 2 should suffice, since my program is four instructions long, (however in this example I use 7), which would be indicated by the pin transition that I see.In fact that is not the issue here.

    The transitions happen as expected and within the required time that I program them with. (See host side code, esp the configNHET() function). The issue is the significantly large dead time after the pulse period has ended.

    Now as you mention that if hr and lr settings are made correctly, which I believe I am, an update/write to the CNT instruction's control dword (max_count field) should set the period of the waveform. and an update/write to the ECMP instruction's data field should control the pulse width between zero to max_count.

    However what I am seeing is that the max_count is much smaller than the compare value stored in ECMP data field.
  • Safiullah,

    I'd say most HET instructions are single cycle, but you have to look at the TRM.   Some are 2-3 cycles.  Plus there is a 1 cycle penalty if you have a remote address = next address for a store.  

    Also if your loop is "N" cycles - you have a max of N-1 cycles of execution.  You need to be back at address 0 by the Nth cycle.   While you could argue that overrun flag may be false in this case - the overrun condition suppresses the pin transitions that were scheduled during the loop where the overrun occurred so it's not a condition that you can have and expect your program to operate. 

    To get an accurate read on the cycle count you can use the N2HET simulator as shown below.   Find the longest path through your code and measure it as shown:

  • By the way, you should also single-step throught your code in this env to figure out why it's not working w. the inputs that you gave it.
    Best Regards,Anthony