[SOLVED] Enable interrupts from inside a timer interrupt

castortiu
Tue Jan 16, 2018 1:45 am
Hi there,

I need to start a timer and make it fire from inside another timer interrupt, basically I need another timer to fire even when the other timer calls has not finished.

Seems that HardwareTimer disable interrupts when it fires because inside timer 2 I start timer 3 but it doesn’t fire until immediate the call to the timer 2 has finished.

The sample below is way oversimplified, but my case is that I need to start timer A when it fires I need to start timer B however timer B may need to fire before the call to A has finished.

Long story short I need to control the brightness of my RGBMatrix, and to do that I need to control the matrix OE (OutputEnable) leg time, however I cannot start this timer until the latch from the last frame has been made, Timer A triggers the latch to make it visible on the matrixx and then proceeds to build the next frame, meanwhile Timer B has to start after the latch and has to be called(fired) to disable OE at an specific time to disable the matrix output.

Hopefully I made myself clear, but the question is very simple, I need to enable interruptions re-entrancy which seems HardwareTimer disables when the interruption fires.

I tried to put interrupts() as first line inside void ISRUpdate but nothing change, ISRUpdate1 is called as soon ISRUpdate finish;
HardwareTimer timerDisplay(2);
HardwareTimer timerDisplayEnabled(3);

timerDisplay.setMode(0, TIMER_OUTPUT_COMPARE);
timerDisplay.setPeriod(100 * microseconds_per_millisecond);
timerDisplay.attachInterrupt(0, ISRUpdate);
timerDisplay.resume();

timerDisplayEnabled.setMode(0, TIMER_OUTPUT_COMPARE);
timerDisplayEnabled.setPeriod(5);
timerDisplayEnabled.attachInterrupt(0, ISRUpdate1);
timerDisplayEnabled.pause();

bool myValue = false;

void ISRUpdate(void)
{
timerDisplay.pause();



timerDisplayEnabled.setPeriod(brightness); // about 100
timerDisplayEnabled.resume();


// Code in here runs for 500 microseconds, 5x more than the time in the line above


timerDisplay.setPeriod(XX);
timerDisplay.resume();

// value of myValue still is false, interrupt for timerDisplayEnabled doesn’t trigger until ISRUpdate which was called from the timer 2
// unwind from the stack.
}

void ISRUpdate1(void)
{
timerDisplayEnabled.pause();
myValue = true;
}


dannyf
Tue Jan 16, 2018 1:54 am
I need another timer to fire

hard to tell what you meant by “fire”.

CMx chips allow priority / subpriority over its interrupts so take a look at the datasheet to see how that can be set-up – the ISRs are re-entrant.

another feature is interrupt-chaining (potentially what you are trying to do), whereby a pending ISR can be executed without the exiting the current ISR, reducing ISR latency.

With that said, generally you don’t need something this fancy so your “problem” potentially has a solution vastly different from your current approach.


castortiu
Tue Jan 16, 2018 2:01 am
By fire I mean when the timer time elapses and calls the interrupt method.
Is not fully re entrant what I want to do as you mention really is interrupt-chaining, since I want Timer B to be called even when Timer A has not finished.

I wish there was a simpler solution but predictable I need to disable the OE at a particular time (just set the output to high), Timer A is executing a bunch of high perf code to build the next frame, so it can’t stop to check if the elapse time to disable the OE is done, basically the check would have to be done at every line and consume more CPU than the code to build the next frame. Also Timer B for the OE has to be started only once the matrix data has been latched, so the Timer B has to start from Timer A interrupt.


victor_pv
Tue Jan 16, 2018 3:23 am
As dannyf said different interrupts have different priorities. Check the datasheet to see which of the timers have higher priority, and that one should be able to “fire” within the other one.

castortiu
Tue Jan 16, 2018 6:46 am
Thank you!!!
Setting the priorities did the job.

nvic_irq_set_priority(NVIC_TIMER2, 15);
nvic_irq_set_priority(NVIC_TIMER3, 0);


dannyf
Tue Jan 16, 2018 11:15 am
I’m not convinced yet that you need something that fancy.

the first question should be if the OE pin can be enabled in the middle of a frame transmission. if yes, you can simply drive it with a pwm pin. 0-100% duty cycle.

if the OE pin can only be enabled at the end of a frame transmission, your ISR flow should be like this:

timerA isr:
[optional]disable the OE pin;
transmit the frame; //assuming it is short
enable the OE pin;
enable timerB; //can be done with 1 instruction
exit;


castortiu
Wed Jan 17, 2018 5:09 am
The code that you put in there is almost identical to what I use with two timers, however I’m driving the the matrix on BCM and not on PWM for the tones so before I resume the timerB, on timerA isr I need to set a specific time on timerB since the time to be the OE is dependent of the weight of the bit column that is been process at that time, since I have 16 tones per color, the OE time is enabled in multiple of 2 4 times.

When brightness is at 15 latency is not an issue since, the OE enabled times are 16µs, 32µs, 64µs, 128µs for the 4 bits however definitely latency is an issue when the brightness is at 0 since for the 4 bits I need to enable bit 0 for 1µs, bit 1 for 2µs, bit 2 for 4µs and bit 3 for 8µs, the timerB handler for the bit 0 lags about 700ns so ends up with a pulse of 1.7µs instead 1µs. then when brightness is at 0 colors tones 1, 3, 5, 7, 9, 11, 13, 15 won’t render perfectly but can’t really be noticed.

I thought about driving the OE with PWM however I was afraid (theory) that the display will display artifacts if when OE is enabled/disabled during latching and was looking for something more predictable.

However for testing I’ll try to drive OE with PWM only after latch completed and before the previous frame starts, if that works I don’t need timerB


castortiu
Wed Jan 17, 2018 5:57 am
I uploaded a video to show the current progress of the brightness control, here I set the brightness to zero and the 700ns ISR lag make odd numbers slightly “brighter” when brightness is zero, isn’t noticeable at all however I’ll try to use PWM to control OE

RGB animated matrix
viewtopic.php?f=19&t=3104

.


dannyf
Wed Jan 17, 2018 11:59 am
for indoor applications, duty cycle of 0.1% or lower is indistinguishable from dark, even if high brightness LEDs are involved. that percentage is higher for outdoor applications.

so if you are refreshing your display at 100Hz (way higher than necessary), the minimum on cycle you need to hit is 0.1% * 10ms = 10us. On a 72Mhz mcu, that translates into 720 ticks. shouldn’t be a problem.

if it is, there are other ways to address the minimum dc issue.


castortiu
Wed Jan 17, 2018 5:17 pm
I rerouted some pins so OE ends up on a PWM pin, I did a basic test and PWM runs by default at 1Khz which is no even close enough what I need, the matrix produce a huge flickering artifact barely it can be distinguish the content of the animation, I need to run the PWM at least 1000 times faster.

In the case of the RGB matrix and BCM I need to run at least at 200hz refresh rate or artifacts start to present, this is better described here
http://www.batsocks.co.uk/readme/art_bcm_1.htm

The time slice for bit 0 is just 15μs, if I run continuous PWM on OE without care of sync with latch then I would need at least 10 pulses of PWM for every bit to avoid artifacts which would translate on a 1μs period or 1Mhz PWM.

How do I change the default PWM frequency of 1Khz? On Arduino seems to be with setPwmFrequency() however seems this function is not available on STM32.

Another way would be to sync enabling the PWM on the beginning of every bit when the bit latch then I would need fewer PWM pulses since duty cycles will be fair for all bits however the default 1Khz is not even close for that either.

In the image you can see
D: is a whole frame (250Hz)
OE: running PWM at 1Khz (which a single period is taking what it takes 4 pixels to render)
Latch: Is when the data of every bit is send to the matrix, there is a zoom for bit 0 that takes 15μs, if I want PWM to work I need to fit at least 10 PWM OE pulses in there or fewer pulses if I can synchronize with the latch going low.

By the way I’m running the blue pill overclocked at 128Mhz.


stevestrong
Wed Jan 17, 2018 6:44 pm
Well, I cannot see why you would anyway need BCM, that’s just PWM with repeatedly variable duty cycle.
IMO, this is equivalent to a “normal” PWM with constant duty cycle, wherein you have to keep the total low/high pulse ratio within a BCM period.
What also important, I think, it is the highest allowable OFF cycle to avoid flickering, which would be ~= the total period of a BCD train.

When you talk about 200Kz, what exactly is this referring to? To the period of one pulse or the total period of a BCM train?

The F103 timer PWM is very powerful, capable to set up in very different ways. You could also do some sync with other pulses when needed.
Do you have a plot showing how exactly your signals should look like? If possible with periods on it?


dannyf
Wed Jan 17, 2018 6:48 pm

I need to run the PWM at least 1000 times faster.

It is certainly possible to run the pwm module at 1Mhz.

But when your requirement becomes that extreme for such a simple task, you may want to re-examine your approach, both software and hardware.

Case in point. Ppm is often used as a software implementation of pwm, when the hardware isn’t available. It is not intuitive to implement ppm through a pwm hardware module.


victor_pv
Wed Jan 17, 2018 7:00 pm
There is also the option to feed a timer from another timer.
I don’t remember all the details, the datasheet shows what it can do, but perhaps that can remove the need to have 2 ISRs completely and leave only 1.
I think that one of the modes is to enable the second timer to count once the first time reach a certain count, which I understand is more or less what you are trying to do with the 2 timers and the ISR.

castortiu
Wed Jan 17, 2018 7:11 pm
I’m not sure when I talked about 200Khz?, only thing I mentioned was that I want to keep the refresh rate above 200Hz.

Still didn’t get any hint how to change the PWM frequency. Do you know how?

Current approach with two timers works fine, and blue pill only take care of rendering so the current approach is good enough, however when brightness is at minimum the isr introduce a 700ns latency which isn’t big deal.

However I keep looking for alternatives, if I can drive PWM at 1Mhz I may not need the secobd timer however from what I read PWM uses a timer as well, so is not that I’m saving a lot other than some code.

Anyway… anything is on the table to change,

How do I change the pwm frecuency?

Thanks!!


Pito
Wed Jan 17, 2018 7:16 pm
Still didn’t get any hint how to change the PWM frequency. Do you know how?
viewtopic.php?f=19&t=3037#p39304
viewtopic.php?f=19&t=3037&start=10#p39347

castortiu
Thu Jan 18, 2018 6:34 am
Handling the OE with PWM works great, as long I keep the PWM above 400Khz it doesn’t produce any artifact for lower tones since even bit 0 which is the shortest will have up to 8 pulses and I don’t need to synchronize with the latching, the reality in my testing I could go down to 200Khz before I started to see some evidence that tones are changing specially when I put a gradient test screen, so I bumped PWM to 400Khz and is rock solid, definitely now with PWM I have a much accurate control of the brightness than ISR chained event.

Thanks!!!!!

By the way now I know where the pink pins info is used in the image :)
However still I don’t have clear for example, PWM on PB0 is controlled by T3C4 (Timer3 Channel 4) but what means T1C3N next to it???


castortiu
Thu Jan 18, 2018 6:54 am
I uploaded a video to youtube to show how smooth is now the steps in control of the brightness with OE and PWM, the phone I have seems to be really good a low light so in the video can’t be appreciated but there is a huge difference between brightness (0) and (15).

After playing the video several times during second 3 and 4 I see some artifacts that can’t be seeing with the naked eye but on the video looks like some pixel ghosting, I did not have that before, I wonder if the PWM frequency is the problem since is not synchronized with the latching, I’ll see if increment the PWM to 1.28Mhz have the same issue.


castortiu
Thu Jan 18, 2018 8:08 am
On further testing I confirmed what I was afraid, “unsynchronized” PWM on OE brings undesirable artifacts to the display, I bumped the PWM frequency from 400Mhz to 1.2Mhz and is barely noticeable however the artifacts are still there as you can see in the image below with and without PWM.

I would bet anything that is because the PWM is not synchronized with the latch so the OE is going low and enable the display while the data is still feed into the shift register.

Well… going back to the drawing board :(

My guts tells me if I synchronize the OE PWM start/stop with the latch this problem will go away, also synchronizing will make the number of pulses constants when the display is visible so I suspect that just lowering to 200Khz (about 4 pulses for bit 0) will be more than enough since now the duty cycle will be the fair and same for every bit, it would require some extra lines of code as it did with the 2 ISR timer chained events, however I think it will work.


dannyf
Thu Jan 18, 2018 11:34 am
There is also the option to feed a timer from another timer.

having the master to trigger to slave; or running the slave in single pulse mode….

what means T1C3N next to it???

negative.


castortiu
Fri Jan 19, 2018 6:09 am
Synchronizing the OE with the latching works like a dream and there is no artifact problem at any brightness level and I can go as low as 300Khz for the PWM without any problem. At this point I can’t be happier and don’t think I’ll make any more changes on the display brightness.

Steve wrote,
“Well, I cannot see why you would anyway need BCM, that’s just PWM with repeatedly variable duty cycle.”

From what I researched with BCM I need way fewer instructions to display a frame with 128×32 at 16 tones achieving much higher refresh rate of at least 250Hz.

Currently the main loop to display a frame is basically; cycle for the instructions I put below with barely any extra processing.
Based my work from the explanation http://www.batsocks.co.uk/readme/art_bcm_1.htm however the implementation was initially the Adafruit RGB matrix driver implementation that I heavily end up modifying..

Instructions to create a frame:
(1 x reset PWM OE) + (1 x set latch) + (1 x Row Address = “2 rows per instruction”) + (128 x clock set) (1 x R1G1B1&R2B2G2 data “6 colors set per instruction”) + (128 x clock reset) + (1 x set PWM OE)) x 4 bits x 16 rows = 16704 instructions per frame

so with 16704 instructions I can display a whole RGB frame on the matrix, may be possible but honestly down know how to make it happen with PWM instead BCM.


stevestrong
Fri Jan 19, 2018 10:05 am
I would gladly tell you how to set the PWM but I have no idea about your requirements, about the relationship between PWM frequency, refresh rate, display resolution, and about all the required signals (and the synchronization among them) in general.

dannyf
Fri Jan 19, 2018 12:30 pm
if it has serial inputs, a latch and an OE pin, it is likely that it is based on serial shifters like HC595 where the OE pin is completely unhinged from the input circuitry.

implementing ppm over pwm hardware just makes zero sense.


castortiu
Fri Jan 19, 2018 6:07 pm
Yes, most of these matrix are based on shift register. And have different scan lines.
Most usual is 1/16. Means it has 4 lines A,B,,C,D to control the row 1-16- & 17-32, so if the address is 0b0001 then data will be sent to row 1 AND 17, however has two data lines per color R1, R2, G1, G2, B1, B2 so after every latch every change in address plus the 6 data lines to control colors in two rows at the same time, there are other matrix that are 1/32 Means that address lines are A,B,C,D,E and just R,B,G, however 1/32 are great to control matrix of 64 rows since usually have an extra address line A, B,C,D, E and R1, R2, G1, G2, B1,

beyond the address and data bus there are 3 more lines, latch, clock outputenable

Start to set the address/data while sending the train of clock pulses (128 for 128 columns), then latching sends the data to the LEDs.
Output enable is just a switch to “turnon/turnoff” the whole display.

To making it very simple, how would you implement a PWM control with 1 row, 8 columns, 16 tones, monochromatic at 250Hz refresh rate with 3 wires? After that is just a question of scale.

Basically you have 3 wires to control 8 LEDs in a row
R – Data line
L – Latch
C – Clock


dannyf
Fri Jan 19, 2018 7:37 pm
looks like yours has a 16:4 mux that controls which line is on, and then 3 sets of shift registers, for R/G/B.

if I were to write a driver for this, I would establish a buffer: it contains information about the display’s construction (including current frame index, or brightness) and frames. If you write a slave receiver here (spi or uart), you can turn the controller-less display into a common / universal display and commercialize it potentially. In that set-up, the master can simply communicate to the display unit with command data + images and the slave will handle the rest.

each frame then contains a current index for the line being scanned.

a display routine is periodically called from the isr. The display routine would perform something like this:

1) fill the shift registers with line data;
2) turn on the current mux line; this assumes that the mux lines cannot be turned off.
3) strobe out the shift register data;
4) advance the line index to the next line;

the logic is slightly different if you use DMA under-run interrupt in step 1) above.

Your OE line is driven separately via a pwm module – using the OE pin to a PWM a HC595 has been done for ages.

You can take a look at this basic logic at work here (https://dannyelectronics.wordpress.com/ … ment-leds/) and here (https://dannyelectronics.wordpress.com/ … ment-leds/) and here (https://wordpress.com/post/dannyelectro … s.com/4113).

The actual implementation will be different, the hardware involved will be different but the basic logic is the same.


castortiu
Sat Jan 20, 2018 2:21 am
“if I were to write a driver for this, I would establish a buffer: it contains information about the display’s construction (including current frame index, or brightness) and frames. If you write a slave receiver here (spi or uart), you can turn the controller-less display into a common / universal display and commercialize it potentially. In that set-up, the master can simply communicate to the display unit with command data + images and the slave will handle the rest.”

If you look at my previous posts with Steve about slave DMA SPI this is exactly what the blue pill job does, it is a RGB Matrix rendering driver :)

The blue pill only function for me is use the SPI bus to take an input of ARGB (1555) frames and display them on the matrix, internally is using a DMA buffer for SPI and double buffer for the Matrix data to avoid tearing of the screen, doing this way I have the whole ESP8266 CPU to create frames with my graphic library as the Clock, Animations, blending, effects, OSD (on screen display) with alpha support, etc and then send the frame as is to the blue pill where it take care of encoding the ARGB (1555) frame into whatever the matrix understands, in this case RGB (444)

In fact I can disconnect the ESP8266 from the STM and the last frame will keep rendering on the matrix, also the SPI bus is full-duplex where I can send instructions from the ESP as get/set rtc, set the brightness of the display from the ESP8266 or control other things like the buzzer (STM also has coded a tone synthesizer that is driven over the same SPI bus), the STM DMA bus also is driven with an interruption over the CS so the DMA buffer self-heal when receives corrupted data, also has other cool features as partitions of frames since sending a full frame from the ESP would take some time and the STM will take some time to decode a full frame as well, this synchronization would slow down the two CPUs, instead the ESP8266 sends 1/8 of a frame at the time arbitrarily so the SPI burst transition from ESP to STM is very short and give time to the STM to decode 1/8 of a frame while is receiving another 1/8 frame in the DMA buffer in parallel.

This behaviors allow as very high speed animation to automatically omit sending some portion of the frame since a new 1/8 of frame is coming behind, means the animation will never be slow down because of the CPU processing, collateral effect will be that just some frames may be skipped, that’s all

Your 4 points seems a generalization how to do it however doesn’t share any hint or mechanic how pwm is used to give different tones for every pixel, still reading what you mean, also I’ll go over all the links, however if I can understand well the following, then I can scale it as well,

PWM with 3 wires to control 8 LEDs in a row
R – Data line
L – Latch
C – Clock

With BCM I need only 4 very short clock pulses plus 4 latches to display a pixel with 16 tones. In the case of 128 columns just 128×4 clocks plus 4 latches. how many clock cycles and latch do you need to display a pixel with 16 tones with PWM?


castortiu
Sat Jan 20, 2018 5:48 am
By the way I did work with shift registers as well, that’s not new to me, in fact my first raw Red Matrix version about 3 months ago was using 74hc595d discrete components and did good progress, I made work the matrix in the image below with an Arduino nano for a 24×32 just red channel a 60Hz, 16 tones of red using my own PWM algorithm, until I found out that I could get from China fully assembled RGB panels 128×32 with the controllers embedded for about the same price, so there was no way I could make something even remotely close similar myself for the same price so I redirected my effort on understand and make the matrix works, using my own PWM algorithm discovered that I would need something at least 100 times more powerful than the Arduino nano to make it work there is where I found the STM32 and start to post here :)

The research lead me to BCM, I know my own PWM implementation sucks, and I’m interested to know what you have in mind at this scale. Remember that the matrix is 128×32 and has 6 shift registers R1, R2, G1, G2, B1, B2 and want to have high refresh rate, so the PWM algorithm needs to be very efficient, most than everything I’m interested to learn an efficient PWM technique.

If I would use my own and old PWM algorithm I would need 128 clocks * 16 latches, that would be almost 4 times greater than BCM and basically probably I could get only 60Hz instead 250Hz.

The original idea in the images below was to chain 74hc595d controllers vertically and horizontally to control a larger Matrix 128×32 and replacing only the MCU, so naive myself that I thought with 16Mhz was enough to do all that.


zmemw16
Sat Jan 20, 2018 2:47 pm
please tell us(me) how those pcb’s were made ?
couple by etch resist pen hand drawn ?
and the ones with very, very clean isolation cuts ?
stephen

dannyf
Sat Jan 20, 2018 2:54 pm
o the PWM algorithm needs to be very efficient

that’s probably the disconnect. Take a look at hc595’s datasheet and see how the OE pin works with respect to the rest of the circuitry.


dannyf
Sat Jan 20, 2018 2:56 pm
20180119_211651.jpg (241.71 KiB)

for large matrix, that’s a pin efficient but not time efficient implementation: as the row data is serial as well.

a better approach is to use a mux (or multiples of them).


castortiu
Sat Jan 20, 2018 3:50 pm
“please tell us(me) how those pcb’s were made ?”

Started with electronics again as a hobby about 5 months ago after 20 years of doing nothing with electronics so I was trying to find a quick method to iterate and create prototypes.

1) The board in the center was made with paper toner transfer and etching with ferric chloride, I tried about 10 different methods, I never could master the process, even bought new printers, papers, chemicals and so on, big failure so far, always for one reason or another some toner is not transferred and had to hand touch with a pen, as you can see in the image I sent before. Currently the boards I do with toner transfer are not all bad however I cannot go below 80mil traces, unusable unless is a very basic PCB.

2) The PCBs on the side are made with a CNC machine, these were made about 30 days after trying many techniques with the machine, at first they were a mess and started to improve the technique, probably I did about 100 PCBs until vastly improved the technique, these boards are old, at this moment after 5 months I “mastered” the process and I do my double side PCBs with a 15mil traces and they look 10 times better than the picture above.

3) Started to play with Pre-sensitized PCBs, transparencies and UV light, however Pre-sensitized PCBs are way too expensive, so dropped this technique in favor of the CNC machine, however Pre-sensitized PCBs can gain quite a bit of time for complex PCBs since the CNC machine can be working for 1hr or more for every side.

These are some of the keys in the technique I’m using.
a – Use good carving bit with a .1mm tip
b – Center the carving bit with a strobe light
c – Make a thing layer of WD40 while the machine is carbing
d – Pre-level the work surface
e – Secure the PCB to the machine very flat using double side tape.
f – Autolevel algorithm to measure imperfections of the PCB and readjust bit height in the source file

At this moment my CNC machine carves only 0.05mm from the copper, so the carving bit barely touch the fiber glass.

I’ll see if I find new PCBs to show how they looks like, they are really good at this time.

This is the machine I got:
https://www.ebay.com/itm/USB-3Axis-CNC- … 25e8de4d39

I had to make some modifications to the machine to add an autolevel input since by default these machine do not have them.


Leave a Reply

Your email address will not be published. Required fields are marked *