Jump to content

Timer or Tick?


wackazong

Recommended Posts

I need a function that is repeated with a frequency of about 4000Hz (4000 calls of the function per second). I implemented it in two ways: one just puts the function in void Tick(void) __wparam in the main.c sceleton, the other puts it in void Timer(void) __wparam, and initialises the timer with MIOS_Timer_Init(0x03, 50).

The one which just uses Tick works beautifully, and the core stays responsive, while the other one does not work at all, only when I increase the second paramer of the init to 100. But also then the function is awfully slow. The core is also responsive then, but the function does not work as expected.

I know that Timer uses an interrupt routine, but why doesnt this work with Timer when it works with Tick?

This is the code that is called (Flash_Handler is called, and uses Interpolate32):

/////////////////////////////////////////////////////////////////////////////
// Interpolate
/////////////////////////////////////////////////////////////////////////////
unsigned char KNOEPFLI_Interpolate32(unsigned char step, unsigned char value1, unsigned char value2)
{
	unsigned char swap, diff;

	//send out value2 if step is the max value
	if( step == 32 ) {
		return value2;
	};
	//send out value1 if step i 0
	if( step == 0 ) {
		return value1;
	};
	//invert the interpolation if value1 > value2
	if( value1 > value2 ) {
		//swap the values
		swap = value2;
		value2 = value1;
		value1 = swap;
		//--step because we are counting from 0 to 32, not to 31
		--step;
		//invert the step counter
		step = ~step;
		//clear the upper three bits
		step &= 0x1f;
	};

	//get the difference
	diff = value2 - value1;

	//divide it through the total number of steps (>>5) and multiply it with step (gives an integer) then get the high byte, 

	//shift the step counter three to the left to make it 8bit, store it in PRODL
	PRODL = step << 3;

	//store diff in PRODH
	PRODH = diff;  

	//do the multiplication in assembler
	__asm
    movf _PRODL, W
    mulwf _PRODH, 0
	__endasm;

	//add the lower value
	return value1 + PRODH;

}

/////////////////////////////////////////////////////////////////////////////
// Flash Handler
/////////////////////////////////////////////////////////////////////////////
void KNOEPFLI_Flash_Handler()
{
	unsigned char red, green, blue;

	if( knoepfli_led_status[knoepfli_led_counter].FLASH == 1 ) {

		red = KNOEPFLI_Interpolate32( knoepfli_led_flash_counter[knoepfli_led_counter], knoepfli_led_color_now_red[knoepfli_led_counter], knoepfli_led_color_flash_red[knoepfli_led_counter]);
		green = KNOEPFLI_Interpolate32( knoepfli_led_flash_counter[knoepfli_led_counter], knoepfli_led_color_now_green[knoepfli_led_counter], knoepfli_led_color_flash_green[knoepfli_led_counter]);
		blue = KNOEPFLI_Interpolate32( knoepfli_led_flash_counter[knoepfli_led_counter], knoepfli_led_color_now_blue[knoepfli_led_counter], knoepfli_led_color_flash_blue[knoepfli_led_counter]);

		//Send Brightness red
		MIOS_IIC_Start();    // start IIC
		MIOS_IIC_ByteSend( knoepfli_led_address_red[knoepfli_led_counter].DRIVER ); // send device address, bit #0 cleared to notify a write!!!
		MIOS_IIC_ByteSend( 0x02 + knoepfli_led_address_red[knoepfli_led_counter].LED );  // select brightness register of the corresponding led, the first one is 0xa2, no autoincrement
		MIOS_IIC_ByteSend( red );  // send brightness
		MIOS_IIC_Stop();

		//Send Brightness green
		MIOS_IIC_Start();    // start IIC
		MIOS_IIC_ByteSend( knoepfli_led_address_green[knoepfli_led_counter].DRIVER ); // send device address, bit #0 cleared to notify a write!!!
		MIOS_IIC_ByteSend( 0x02 + knoepfli_led_address_green[knoepfli_led_counter].LED );  // select brightness register of the corresponding led, the first one is 0xa2, no autoincrement
		MIOS_IIC_ByteSend( green );  // send brightness
		MIOS_IIC_Stop();

		//Send Brightness blue
		MIOS_IIC_Start();    // start IIC
		MIOS_IIC_ByteSend( knoepfli_led_address_blue[knoepfli_led_counter].DRIVER ); // send device address, bit #0 cleared to notify a write!!!
		MIOS_IIC_ByteSend( 0x02 + knoepfli_led_address_blue[knoepfli_led_counter].LED );  // select brightness register of the corresponding led, the first one is 0xa2, no autoincrement
		MIOS_IIC_ByteSend( blue );  // send brightness
		MIOS_IIC_Stop();

		if( knoepfli_led_flash_counter[knoepfli_led_counter] == 0 ) {
			knoepfli_led_status[knoepfli_led_counter].FLASH = 0;
		} else {
			--knoepfli_led_flash_counter[knoepfli_led_counter];
		};
	};

	//increase the counter for the next run of the routine
	++knoepfli_led_counter;

	if( knoepfli_led_counter == KNOEPFLI_LED_NUMBER ) {
		knoepfli_led_counter = 0;
	};

}

Link to comment
Share on other sites

Hi,

this should give an answer:

Timer() would be a bad choice, because it interrupts the main task, and could therefore also interrupt a MIDI stream; this could result into sporadically sent invalid MIDI events.

So, if timed transactions are required, the Timer should request a send, and Tick() should check for this request flag, clear it and send the events (similar to the approach used for DISPLAY_Tick())

so: the right approach would be to set a flag at the Timer() notification and then process it (if enabled) within Tick()

Regards,

Michael

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...