Yes. It's just like the other native mode ZX devices except that it has less RAM and Program Memory as well as fewer I/O pins.sturgessb wrote:Could that be set up to be an I2C slave?
multiple PWM capture
Very interesting.dkinzer wrote:Another option is the 28-pin ZX-328n, soon to be announced. It is currently available in limited quantities but we expect to have ample stock within a week or so.
Some of the newer 8-bit PICs (in the 18F family) have register bits that allow switching polarity for the hardware USARTs. Do any of the AVR chips allow this?
The CS10 identifier is defined in some device-specific include file to be the bit number of that control bit. The << operator in C is shift left so (1 << CS10) just creates a value with a particular bit set. The |= operator in C means to take the value on the left, logically OR the value on the right and write it back.sturgessb wrote:TCCR1B |= (1 << CS10); // Set up timer
The equivalent in ZBasic would be:
Code: Select all
Const CS10 as Byte = &H01
Register.TCCR1B = Register.TCCR1B Or CS10
Code: Select all
If Semaphore(Register.Timer1Busy) Then
Register.TCCR1A = 0
Register.TCCR1B = &H01
Register.TCCR1C = 0
End If
- Don Kinzer
Thanks Don, got it working now!
prescale of 8 seems to be a good match.
Maybe an 8 bit timer would be good enough, i presume that is TCNT2. are all the setting for that timer in TCCR2?
EDIT: Cool timer 2 can give max resolution of 1-200 steps for RC receiver channels, thats not far off the 255 standard range. I take it there are no other tricks to dealing with timer overflow, can it be detected and then added to the following count? if that makes sence?
Cheers
Ben
prescale of 8 seems to be a good match.
Maybe an 8 bit timer would be good enough, i presume that is TCNT2. are all the setting for that timer in TCCR2?
EDIT: Cool timer 2 can give max resolution of 1-200 steps for RC receiver channels, thats not far off the 255 standard range. I take it there are no other tricks to dealing with timer overflow, can it be detected and then added to the following count? if that makes sence?
Cheers
Ben
at the moment I have the following code in a task...
would there be any performance benefit to changing this to an ISR?
Code: Select all
Call WaitForInterrupt(zxPinRisingEdge, 0)
Register.TCNT2 = 0 'reset to zero
Call WaitForInterrupt(zxPinFallingEdge, 0)
tempint = Cint(Register.TCNT2)
Perhaps. In your code there will be a task switch between the time when the external interrupt occurs and when the timer is read. If you used an ISR, it is likely that there would be less latency until the timer is read.sturgessb wrote:would there be any performance benefit to changing this to an ISR?
For multiple channels, you won't be able to set the timer to zero. Essentially, you just want the difference between the timer readings at the beginning and the end of the pulse, accounting for timer rollover. You'll probably also want an ISR for timer overflow in which you would increment another 16-bit variable. This would effectively give you a 32-bit timer value.
Code: Select all
Structure pwmData
Dim isValid as Boolean
Dim width as UnsignedLong
End Structure
Dim timerHigh as UnsignedInteger
Dim pwm0Data as pwmData
Dim timerData(1 to 2) as UnsignedInteger
Dim width as UnsignedLong Alias timerData
ISR TIMER1_OVF()
' increment the high word of the timer value
timerHigh = timerHigh + 1
End ISR
ISR INT0()
Const INT_MASK as Byte = &H03
Const INT_RISING as Byte = &H03
Const INT_FALLING as Byte = &H02
' store the timer value
timerData(1) = Register.TCNT1
timerData(2) = timerHigh
' see if the trigger was the rising or falling edge
If ((Register.EICRA And INT_MASK) = INT_RISING) Then
' rising edge, reset for falling edge trigger
Register.EICRA = (Register.EICRA And NOT INT_MASK) Or INT_FALLING
' initialize the data structure for the beginning of a pulse
pwm0Data.width = width
pwm0Data.isValid = False
Else
' falling edge, reset for rising edge trigger
Register.EICRA = (Register.EICRA And NOT INT_MASK) Or INT_RISING
' compute the pulse width
pwm0Data.width = width - pwm0Data.width
pwm0Data.isValid = True
End If
End ISR
- Don Kinzer
You have pretty much written all of the required code now, Don. However for the ZX328n or ZX24n it is probably better to use the pin change interrupt for 4 I/O pins as there are not enough interrupts for 4 channels.
The ISR would be a little more complicated and additional state would be needed to know which pin was being timed and the start time for each one.
The ISR would be a little more complicated and additional state would be needed to know which pin was being timed and the start time for each one.
Mike Perks
As I said in one of my earlier appends, you could reset the timer to zero in one of the periods when all 4 timers are idle or when the first new interrupt arrived.dkinzer wrote:Perhaps, but it is completely untested, however. One issue that is not handled is overflow of the timerHigh variable.
Mike Perks
Thanks for the code Don, going through it now.
Do i need to place the ISR code in any particular place, or put something else in to get it to run. I say this as i just put the following in above Sub Main()...
I know that timer2 will be overflowing, but tempint is not increasing. any ideas?
Ben
Do i need to place the ISR code in any particular place, or put something else in to get it to run. I say this as i just put the following in above Sub Main()...
Code: Select all
ISR TIMER2_OVF()
tempint = tempint + 1
End ISR
Ben
Using the 18mS dead time between the PWM pulses is an interesting approach. You may be able to tell when you have passed the 2mS period of PWM pulses and have a free 18 or so mS to do post-processing.
I am concerned about the ability to accurately and precisely measure the PWM pulse widths. You will need some careful control of extraneous interrupts. I really wonder if any of the ZX-XXXx models will suffice when the operating system is going to take ofer for a moment at unexpected times.
Not counting any operating system overhead, an interrupt probably has something like 20 clock cycles of overhead before you actually do the interupt processing, then at least 20 clock cycles of processing work. Call it a nice round 50 clock cycles. At 14MHz, then is 3uS per interrupt.
This seems to put an upper limit of precision of measurement of the pulse width to about 280 levels. Is this sufficient precision?
I think that if your were doing the same process on a ZBasic OS chip, that the upper limit of precision would be noticeably worse.
BTW, from what little I know about FPGA hardware (after playing with one for a couple of days!!), it could do this in its sleep. Not that I could tell one how to do it....
-Tony
I am concerned about the ability to accurately and precisely measure the PWM pulse widths. You will need some careful control of extraneous interrupts. I really wonder if any of the ZX-XXXx models will suffice when the operating system is going to take ofer for a moment at unexpected times.
Not counting any operating system overhead, an interrupt probably has something like 20 clock cycles of overhead before you actually do the interupt processing, then at least 20 clock cycles of processing work. Call it a nice round 50 clock cycles. At 14MHz, then is 3uS per interrupt.
This seems to put an upper limit of precision of measurement of the pulse width to about 280 levels. Is this sufficient precision?
I think that if your were doing the same process on a ZBasic OS chip, that the upper limit of precision would be noticeably worse.
BTW, from what little I know about FPGA hardware (after playing with one for a couple of days!!), it could do this in its sleep. Not that I could tell one how to do it....
-Tony
another quick question. When using PulseIn, the docs state that it waits for the input pin to be in the idle state, and then waits for it to change to specified logic, and then obviously times the duration of that state.
When its waiting for the idle state and to reach desired logic, does it only halt the task its in, or the entire mcu?
When its waiting for the idle state and to reach desired logic, does it only halt the task its in, or the entire mcu?
The ISR can go anywhere. There is, of course, additional setup that is required. I didn't provide a complete program; just two prospective ISRs.sturgessb wrote:Do i need to place the ISR code in any particular place, or put something else in to get it to run. [...] I know that timer2 will be overflowing, but tempint is not increasing. any ideas?
In order to get the Timer1 Overflow ISR to execute, you have to configure the timer for the correct clocking rate (as we've previously discussed) and enable the interrupt on overflow. The AVR has a global interrupt enable/disable but it also has a means to enable/disable each individual interrupt as well. On the mega1280, the Timer1 interrupt enable flags are in the register TIMSK1. The register TIFR1 contains flags that indicate if an interrupt would occur were it enabled. With this additional information in mind, the timer setup might look like this:
Code: Select all
If Semaphore(Register.Timer1Busy) Then
Register.TCCR1B = 0 ' ensure that the timer isn't running
Register.TIFR1 = &Hff ' clear all pending timer interrupt flags
Register.TIMSK1 = &H01 ' enable the overflow interrupt
Register.TCCR1A = 0
Register.TCCR1C = 0
Register.TCCR1B = &H01 'start the timer running
End If
- Don Kinzer