I'm experimenting making two independent sinewaves (any frequency over the audio spectrum), with each sample triggered by an 8 bit timer interrupt acting as a samplefrequency generator (for the ISR sub) at 62,5kHz.
It produces a stable sinewave while running other code in the do loop. That is the idea.
The odd thing is that after I increase the code in the interrupt sub at a certain point the period between interrupts gets longer. There is about 16us between interrupts. When the code takes more than about 8us, the re-trigger period starts increasing (changing the frequency of the sine waves).
What is it needing so "much" time?
Timer stuff? Interrupt stuff?
mE nO unDerStaNd.
The NOT var may work as this is faster. Do check its use.
Using ROTATE uses the MCUs RRF instruction. A lot faster than calling the >>.
See what this does.
SubMyISRPORTE.1=1ifNOT[WORD]aaa=0thenaaa=0aaa=aaa+1002'changes frequencyaaaout=soundarray(aaa_H)if NOT [WORD]bbb=0 then bbb=0bbb=bbb+1000 'changesfrequency//<-- about here the period between interrupts increases with more codebbbout=soundarray(bbb_H)//about30usseemstobeusedresettingthetimerandtriggeringthe//ccc=aaaout>>1+bbbout>>1dimtempcalcA,tempcalcBtempcalcA=aaaoutrotatetempcalcArighttempcalcB=bbboutrotatetempcalcBrightDAC1DATL=tempcalcA+tempcalcBPORTE.1=0EndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, I figured that there were optimisations to be made, but got stuck on the behaviour of the interrupt and figured that I should solve that first.
Rotate tempcalcB right produced heavy distortion. This distortion is there even if I do not add it with tempcalcA. After fiddling a good while I found that if not rotating temcalcA then it gets clean.
If I -Set C off- before rotating Tempcalc B, then it works.
I used >> because it looks faster. I just figured it was so. :) Is rotate right faster even if I have to -Set C off?
By removing block by block, it seems I was fooled by the interrupt triggering got slowed down and missed firing every second time or something. That was what I was measuring. Yes the pattern looked weird...
Isolating parts, I have found that the code inside the MyISR-loop seem to needs 8,5 us to complete, out of 16.
So the 7-8 us left is not enough for interrupt and/or timer to make it for the next event? Is that what to expect?
I now found out that this part is the way hungriest part (although faster than what I wrote):
if NOT [WORD]aaa=0 then aaa=0
Adding one of these adds about 2.7 us each. I guess it is a good idea to avoid words and to limit range or do nested loops. -Wow! I had no idea about the importance of this!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm guessing that my problem (besides the hungry code) is more about the timer than the interrupt. I will try triggering using external interrupt. I need to know if my guess is right.
I tested nested ifnotxxxthenthingy in bytes, but it was slower than word. So now I know that. Atleast for a while.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I not sure that you need to set aaa or bbb back to 0. The word variable will roll over to 0. So, checking a value is 65535 then setting to 0 is not needed.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Funny, I just tested without those and it works!
When I did it yesterday (bytes instead of words), it just went quiet and I couldn't figure out why it didn't just roll over. Maybe some temporary glitch. Once today the program ran 1000 times slower than before, when I sent the same hexfile over to the nanoboard (through USB), it again ran as normal. Huh?? Now that I know that I will resend the program when things does not make sense...
It seems to comfortably play four sinuses simutaneously at 62,5KHz sampling freq. This could also be four samples playing simultaneously and more if they are not to be read at a variable rate.
SO, -GREAT NEWS!
I have now tested with external interrupt and it seems that it needs about 7-8 us between interrupts. -Roughly the same as with the internal 8-bit timer, which is not to blame. Nearly 50% of time of the current sampling frequency I am testing with the 16F17576 at 32MHZ. If I'm in luck and the 64MHz Pics needs the same number of clock cyckles, it is pretty ok in terms of %.
-Now I have a test program and method, so it will be easy to make compares!
(As I only have one 64KHz PIC and it is hooked up for the tiny video project, I don't want to mess with it until I tried the faster USB-serial soon to arrive).
I could also experiment with timing and process more than one sample per interrupt, but it easily get difficult to handle, so.
I tried find info about the minium time for the interrupt to be sent again in the 16F17576 data-sheet without luck. Maybe it is not there or I do not know where to look. I have no idea what is normal and how much it may differ from PIC or PIC or if it origins from somewhere else.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The PIC16F17576 (enhanced mid-range core) lacks a hardware-defined minimum time between successive interrupts for any source. Interrupts are event-driven via flags in the PIR register: once set (e.g., TMR0IF on overflow), they stay latched until cleared in software (this is automatic when using ON INTERRUPT). Clearing allows immediate re-setting if the event recurs—even in the same instruction cycle—leading to potential back-to-back ISR entries (with 3–5 TCY latency, where TCY is the instruction cycle time, defined as the duration for one full machine instruction and calculated as TCY ≈ 4 / FOSC, e.g., 125 ns at 32 MHz).
Remember, compilers ( including GCBASIC ) cache system variables which can increase the latency. You can change this behaviour by the use of Sub Interrupt (see the Help )but with this you must handle all the aspects of interrupt event. This behaviour may be faster but the management is the developers responsibility.
Look at the ASM for On Interrupt... and Sub Interrupt. Very different.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm experimenting making two independent sinewaves (any frequency over the audio spectrum), with each sample triggered by an 8 bit timer interrupt acting as a samplefrequency generator (for the ISR sub) at 62,5kHz.
It produces a stable sinewave while running other code in the do loop. That is the idea.
The odd thing is that after I increase the code in the interrupt sub at a certain point the period between interrupts gets longer. There is about 16us between interrupts. When the code takes more than about 8us, the re-trigger period starts increasing (changing the frequency of the sine waves).
What is it needing so "much" time?
Timer stuff? Interrupt stuff?
mE nO unDerStaNd.
Edit: PIC clock is 32Mhz.
Last edit: Roger Jönsson 6 days ago
Not sure. But, the ISR can be optimised, a bit.
The NOT var may work as this is faster. Do check its use.
Using ROTATE uses the MCUs RRF instruction. A lot faster than calling the
>>.See what this does.
Yes, I figured that there were optimisations to be made, but got stuck on the behaviour of the interrupt and figured that I should solve that first.
Rotate tempcalcB right produced heavy distortion. This distortion is there even if I do not add it with tempcalcA. After fiddling a good while I found that if not rotating temcalcA then it gets clean.
If I -Set C off- before rotating Tempcalc B, then it works.
I used >> because it looks faster. I just figured it was so. :) Is rotate right faster even if I have to -Set C off?
By removing block by block, it seems I was fooled by the interrupt triggering got slowed down and missed firing every second time or something. That was what I was measuring. Yes the pattern looked weird...
Isolating parts, I have found that the code inside the MyISR-loop seem to needs 8,5 us to complete, out of 16.
So the 7-8 us left is not enough for interrupt and/or timer to make it for the next event? Is that what to expect?
I now found out that this part is the way hungriest part (although faster than what I wrote):
if NOT [WORD]aaa=0 then aaa=0
Adding one of these adds about 2.7 us each. I guess it is a good idea to avoid words and to limit range or do nested loops. -Wow! I had no idea about the importance of this!
Keep interrupts short. :-)
Yes, doing nothing is very fast! :)
I'm guessing that my problem (besides the hungry code) is more about the timer than the interrupt. I will try triggering using external interrupt. I need to know if my guess is right.
I tested nested ifnotxxxthenthingy in bytes, but it was slower than word. So now I know that. Atleast for a while.
I not sure that you need to set aaa or bbb back to 0. The word variable will roll over to 0. So, checking a value is 65535 then setting to 0 is not needed.
Funny, I just tested without those and it works!
When I did it yesterday (bytes instead of words), it just went quiet and I couldn't figure out why it didn't just roll over. Maybe some temporary glitch. Once today the program ran 1000 times slower than before, when I sent the same hexfile over to the nanoboard (through USB), it again ran as normal. Huh?? Now that I know that I will resend the program when things does not make sense...
It seems to comfortably play four sinuses simutaneously at 62,5KHz sampling freq. This could also be four samples playing simultaneously and more if they are not to be read at a variable rate.
SO, -GREAT NEWS!
I have now tested with external interrupt and it seems that it needs about 7-8 us between interrupts. -Roughly the same as with the internal 8-bit timer, which is not to blame. Nearly 50% of time of the current sampling frequency I am testing with the 16F17576 at 32MHZ. If I'm in luck and the 64MHz Pics needs the same number of clock cyckles, it is pretty ok in terms of %.
-Now I have a test program and method, so it will be easy to make compares!
(As I only have one 64KHz PIC and it is hooked up for the tiny video project, I don't want to mess with it until I tried the faster USB-serial soon to arrive).
I could also experiment with timing and process more than one sample per interrupt, but it easily get difficult to handle, so.
I tried find info about the minium time for the interrupt to be sent again in the 16F17576 data-sheet without luck. Maybe it is not there or I do not know where to look. I have no idea what is normal and how much it may differ from PIC or PIC or if it origins from somewhere else.
:-) A good update.
The PIC16F17576 (enhanced mid-range core) lacks a hardware-defined minimum time between successive interrupts for any source. Interrupts are event-driven via flags in the PIR register: once set (e.g., TMR0IF on overflow), they stay latched until cleared in software (this is automatic when using ON INTERRUPT). Clearing allows immediate re-setting if the event recurs—even in the same instruction cycle—leading to potential back-to-back ISR entries (with 3–5 TCY latency, where TCY is the instruction cycle time, defined as the duration for one full machine instruction and calculated as TCY ≈ 4 / FOSC, e.g., 125 ns at 32 MHz).
Remember, compilers ( including GCBASIC ) cache system variables which can increase the latency. You can change this behaviour by the use of Sub Interrupt (see the Help )but with this you must handle all the aspects of interrupt event. This behaviour may be faster but the management is the developers responsibility.
Look at the ASM for On Interrupt... and Sub Interrupt. Very different.