multiple PWM capture

Discussion specific to the ZX-1281 and ZX-1280 microcontrollers as well as the ZX-1281 and ZX-1280 Dev Boards.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:ah figured it, needed to be Register.PCMSK2
You are right. I overlooked that detail.

Code: Select all

Sub Main()
  If Semaphore(Register.Timer1Busy) Then
    Register.TCCR1A = 0
    Register.TCCR1B = &H02
    Register.TCCR1C = 0
  End If
  Register.PCIFR = &Hff
  Register.PCMSK2 = Bx0000_0001  ' bit zero only
  Register.PCICR = Bx0000_0100  ' PCINT2, PortC
End Sub 
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

dkinzer wrote:Interrupts are not used to implement I2C master mode but an interrupt is required to implement I2C slave mode.
So seeing as i want to set this up as an I2C slave, which interrupt do i need to not use, is it an external interrupt or one of the ports?

Cheers
Ben
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:So seeing as i want to set this up as an I2C slave, which interrupt do i need to not use, is it an external interrupt or one of the ports?
The I2C interrupt is internally generated and not related to any specific I/O pin. The fact that you want to eventually implement I2C slave code will have no impact on pin choice except, of course, that you need to keep the SDA and SCL pins available.
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

Don, is this the right setup for 8 bit timer 0 on 24n, with overflow interrupt

Code: Select all

Register.TIMSK0 = &H01 'is this right?
Register.TCCR0A = 0
Register.TCCR0B = &H03

ISR TIMER0_OVF()
	tempint = tempint + 1
END ISR
Cheers

ben
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:is this the right setup for 8 bit timer 0 on 24n, with overflow interrupt
Yes but you can't use Timer0 because it is used for the RTC. You'll note that Register.Timer0Busy will always be true on a ZX-24 indicating that it is in use already.

The other 8-bit timer is Timer2 which you can use if you don't use any of the software UART channels (3-6).
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

Hey guys, Can anyone see a way of optimising this any more? Im getting a few random values and not the value stability I was looking for.

So I think I need to get the runtime of the ISR down a bit more more. Could using Naked mode help? Can i get rid of those shr() functions, so everything is inline? any other ideas welcome!

As you can see im using an 8 bit timer, and using overflow to count the highbyte, so im getting a 16 bit timer value. I need to do this as TIMER1 is need for outputcapture. If I use the 16 bit timer for this, I dont get the large random jumps that i get with the 8bit version but the value jitter is still the same.

PWM input is on pins 7-10 on zx24n

Code: Select all


'DECLARATIONS
	PUBLIC timer2Data(1 to 2) as Byte 
	PUBLIC timer2Value As UnsignedInteger Alias timer2Data

	'PWM vars for 2 ports
	PUBLIC PC_i as Byte
	PUBLIC PC_TimerVal as UnsignedInteger
	PUBLIC PC_B1 as byte
	PUBLIC PC_B0 as byte
	PUBLIC PC_BitsChanged as byte
	PUBLIC PC_StartTime(0 to 7) as UnsignedInteger
	PUBLIC PC_Width(0 to 7) as UnsignedInteger

	'OUT
	Const Chan6_Pin as Byte = 6
	 
Sub Main()
	Call PutPin(Chan6_Pin,zxOutputLow) 
	
	'PC INTERUPTS
	Register.PCIFR = &Hff
	Register.PCICR = Bx0000_0100 ' PCINT2, PortC, PORT A
	Register.PCMSK2 = Bx0011_1100 'PORT C
	Register.PCMSK0 = Bx0000_1111 'PORT A
	
	'TIMER 2 8bit
	If Semaphore(Register.Timer2Busy) Then
		Register.TCCR2B = &H02
		Register.TIMSK2 = Bx0000_0001
	End If
	
	'MAIN LOOP
	Do
		Debug.Print PC_width(0) &", "& PC_width(1) &", "& PC_width(2) &", "& PC_width(3)
		Call sleep(0.10)
	Loop
End Sub


'**************************************************************************
ISR Timer2_OVF()
	timer2Data(2) = timer2Data(2) + 1
END ISR

ISR PCINT2()
		PC_B1 = Register.PinC
		Timer2Data(1) = Register.TCNT2
		PC_TimerVal = timer2Value
	PC_BitsChanged = PC_B1 XOR PC_B0
	PC_B0 = PC_B1
	for PC_i = 0 to 3
		'find a changed bit
		if shr(PC_BitsChanged,2) = 1 then
			if shr(PC_B1,2) = 1 then	'if changed pin high 'starts with pin 10 not 12
				PC_StartTime(PC_i) = PC_TimerVal
			else	'pin low
				PC_Width(PC_i) = (PC_TimerVal - PC_StartTime(PC_i))
			end if
		end if
		PC_BitsChanged = shr(PC_BitsChanged, 1)
		PC_B1 = shr(PC_B1, 1)
	next
END ISR

Cheers

Ben
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:So I think I need to get the runtime of the ISR down a bit more more. Could using Naked mode help? Can i get rid of those shr() functions, so everything is inline?
I'm not convinced that the execution time of the ISR is causing the occasional unexpected data values. I would be more inclined to suspect interference from other ISRs; in this case the RTC. If you have access to a logic analyzer, you can add instructions to the ISR to facilitate measuring its execution time. That should suggest which hypothesis to pursue. You can probably also set up the logic analyzer to show you if/when the pin change ISR is not being executed timely, a circumstance that could lead to unexpected data values.

As for the Naked attribute, you can't just add the attribute to the ISR and expect the code to run properly. With that attribute in effect, the compiler omits the generation of some very essential instructions; it becomes your responsibility to include in the ISR all of the essential assembly language instructions to prevent the ISR code from corrupting registers that other code is expecting to remain unchanged. Consequently, use of the Naked attribute is recommended only for those who a) are skilled assembly language programmers, b) completely understand AVR assembly language, and c) understand the register assumptions relied on by the avr-gcc compiler.

As for the shr calls, while it is true that I recommended avoiding System Library calls in your ISR, it turns out that not all System Library invocations result in calls to procedures external to the ISR. I've reproduced below the C code generated by the ZBasic compiler for the ISR that you posted. Comparison of this code with the original ZBasic code reveals that the shr function is realized by using the C operator >>. In fact, there are no obvious function calls anywhere in the generated C code. Further, I claim that the assembly language instructions ultimately produced for the ISR contain no call instructions at all. This can be verified by examining the .lss file (see the discussion in another post on how to do so).

Code: Select all

ISR(PCINT2_vect)
{
  zv_PC_B1 = PINC;
  zv_timer2Data[1 - 1] = TCNT2;
  zv_PC_TimerVal = *zv_timer2Value;
  zv_PC_BitsChanged = zv_PC_B1 ^ zv_PC_B0;
  zv_PC_B0 = zv_PC_B1;
  {
    uint8_t _zv_forEndTemp01 = 3;
    for &#40;zv_PC_i = 0; zv_PC_i <= _zv_forEndTemp01; zv_PC_i++&#41;
    &#123;
      if &#40;&#40;zv_PC_BitsChanged >> 2&#41; == 1&#41;
      &#123;
        if &#40;&#40;zv_PC_B1 >> 2&#41; == 1&#41;
        &#123;
          zv_PC_StartTime&#91;zv_PC_i&#93; = zv_PC_TimerVal;
        &#125;
        else
        &#123;
          zv_PC_Width&#91;zv_PC_i&#93; = zv_PC_TimerVal - zv_PC_StartTime&#91;zv_PC_i&#93;;
        &#125;
      &#125;
      zv_PC_BitsChanged = zv_PC_BitsChanged >> 1;
      zv_PC_B1 = zv_PC_B1 >> 1;
    &#125;
  &#125;
&#125;
- Don Kinzer
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

hmmm, I wonder if the new xmega devices could be the answer for this problem!?

Ben
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

With the ZX-128a1, would it be possible to input capture 6 pwm channels and output 4 hardware pwm channels?

If not what would be maximum possible be.

Cheers

Ben
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

sturgessb wrote:With the ZX-128a1, would it be possible to input capture 6 pwm channels and output 4 hardware pwm channels?

If not what would be maximum possible be.

Cheers

Ben
The XMega 128A4 family has five 16-bit timers. So, I think you can do input capture on 5 channels simultaneously. I have not verified that all 5 pins are independent of each other on the chip.

In my quick inspection of the atmel document, it indicates that there are 4 input capture channels on 3 of the timers, and I did not investigate what they mean by that. AFAIK, one timer will allow one input capture at a time.

-Tony
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

sturgessb wrote:With the ZX-128a1, would it be possible to input capture 6 pwm channels and output 4 hardware pwm channels?
The xmega128a1 has eight 16-bit timers. One of these is used for the RTC leaving 7 for other purposes. The timers are of two types, Type 0 and Type 1, the difference being the number of compare match registers. The Type 0 timers have four compare match registers (thus supporting 4 PWM outputs with a common base frequency) while the Type 1 timers have only two. Each port C through F has one timer of each type, named TCx0 and TCx1, where x is {C, D, E. F}.

The RTC uses TCC1, leaving TCC0, TCD0, TCE0, TCF0 and TCD1, TCE1 TCF1 for other purposes. With careful selection of input capture and PWM channels, you should be able to have six concurrent input capture processes and then use a remaining Type 0 timer for the four PWM channels as long as it is workable to have the same base frequency for the PWM channels.

In contrast to the mega devices, the compare match registers on the xmega can be used for either input or output purposes. Theoretically, then, you could have four input captures running on a single Type 0 timer. The InputCaptureEx() routine, however, does not exploit this capability, being limited to one input capture per timer. If you wanted to perform multiple input captures using a single timer you'd have to write your own ISRs for managing the multiple capture interrupts and the single overflow interrupt.
- Don Kinzer
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

dkinzer wrote:The xmega128a1 has eight 16-bit timers....
oops, sorry for my bad info about the XMega128A4. I looked at the wrong CPU datasheet!

-Tony
sturgessb
Posts: 287
Joined: 25 April 2008, 6:34 AM
Location: Norwich, UK

Post by sturgessb »

Thanks guys.

4 input captures on one timer sure sounds interesting. This would means I could get away with a smaller ic with less timers. Although I don't think the 32a4 would be up to it.

Ben
Post Reply